日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java工作笔记-对反射的进一步理解

發布時間:2025/3/15 java 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java工作笔记-对反射的进一步理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

?

?

基本概念

代碼與實例


?

基本概念

反射的進一步理解:
將類的各個組成部分封裝為其他對象(將一個類的組成部分封裝為其他對象)
就是反射。

?

Java代碼經歷的三個階段:
1. 寫好代碼.java后使用javac,編譯為字節碼文件:xxx.class
?? ?這個階段稱之為source源代碼階段。


3. 當程序要new一個對象時
?? ?這個階段稱之為Runtime運行時階段


2. 把字節碼文件.class加載進內存里面(使用類加載器ClassLoader)
在內存里面會存在一個對象用于描述字節碼文件。這個對象為Class對象。
所以java里面有個Class類。專門用來搞這個字節碼文件的
如:
成員變量(Fields)、構造方法(Constructor)、成員方法(Method)
這個階段稱之為Class類對象階段

?

第三階段都是同過第二階段創建起來的。第二個階段需要第一個階段。

?

反射好處:
? ? ? ? ? 1. 在程序運行過程中操作這些對象。(IDEA這個程序的 某個對象方法的提示,就是反射)
? ? ? ? ? 2. 可以解耦。提高程序可擴展性。

?

獲取Class對象的方式:
有3種方式,對應java代碼經歷的3個階段;
第一個階段只有.class字節碼文件,并沒有在內存中,要把.class加載到內存中生成對象。對應的API為:Class.forName("全類名") 返回class對象;
第二個階段:這個.class字節碼文件已經到內存了,這個時候,只要獲取他就可以了,類名.class,這種方式。
第三個階段:在Runtime時,已經有對象了,這個時候只要 對象.getClass()就可以了。這個getClass()類是在Object里面
的。

?

?

總結下:
? ? ? ? ? 1.Class.forName("全類名");將字節碼文件加載到內存,返回class對象。
? ? ? ? ? 2.類名.class;通過類名的屬性class獲取。
? ? ? ? ? 3.對象.getClass();getClass()方法在Object類中定義

?

?

?

?

代碼與實例

如下代碼:

Person.java

package Object;public class Person {private String name;private Integer age;public Person(String name, Integer age) {this.name = name;this.age = age;}public Person(){}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';} }

Main1.java

import Object.Person;public class Main1 {public static void main(String[] args) throws ClassNotFoundException {//全類名Class cls1 = Class.forName("Object.Person");System.out.println(cls1);//類名.classClass cls2 = Person.class;System.out.println(cls2);//對象.getClass()Person p = new Person();Class cls3 = p.getClass();System.out.println(cls3);//比較下對象:System.out.println(cls1 == cls2);System.out.println(cls1 == cls3);} }

程序運行截圖如下:

結論:
同一個字節碼文件.class在一次程序運行過程中,只會被加載一次,不論通過哪種方式獲取的class對象都是同一個。
第一種方式,多用于配置文件中,讀取文件,加載類
第二種方式,多用于參數的傳遞;
第三種方式,多用于對象的獲取字節碼
?

下面是

Class對象功能:
1.獲取成員變量;
? ? ? ? ? Field[] getFields()
? ? ? ? ? Field getField(String name)
? ? ? ? ? Field[] getDeclaredFields()
? ? ? ? ? Field getDeclaredField(String name)
2.獲取構造方法;
? ? ? ? ? Constructor<?>[] getConstructors()
? ? ? ? ? Constructor<T> getConstructor(類<?>... parameterTypes)
? ? ? ? ? Constructor<T> getDeclaredConstructor(類<?>... parameterTypes)
? ? ? ? ? Constructor<?>[] getDeclaredConstructors()
3.獲取成員方法;
? ? ? ? ? Method[] getMethods()
? ? ? ? ? Method[] getMethod(String name, 類<?>... parameterTypes)
? ? ? ? ? Method[] getDeclaredMethods()
? ? ? ? ? Method getDeclaredMethod(String name, 類<?>... parameterTypes)
4.獲取類名;
? ? ? ? ? String getName()

?

下面先給出變量名的實例

Person.java

package Object;public class Person {private String name;private Integer age;public String a;protected String b;String c;private String d;public Person(String name, Integer age) {this.name = name;this.age = age;}public Person(){}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", a='" + a + '\'' +", b='" + b + '\'' +", c='" + c + '\'' +", d='" + d + '\'' +'}';} }

Main2.java

import Object.Person;import java.lang.reflect.Field;public class Main2 {public static void main(String[] args) throws Exception {//Field[] getFields()獲取所有public修飾的成員變量Class aClass = Class.forName("Object.Person");Field[] fields = aClass.getFields();for(Field field : fields){System.out.println(field);}//獲取及設置a的值Field a = aClass.getField("a");Person person = new Person();Object value = a.get(person);System.out.println("the a is : " + value);a.set(person, "你妹");System.out.println(person);System.out.println("----------華麗的分割線----------");//Field getDeclaredField(String name)Field[] declaredFields = aClass.getDeclaredFields();for(Field field : declaredFields){System.out.println(field);}//忽略修飾符暴力反射,設置值Field d = aClass.getDeclaredField("d");d.setAccessible(true);d.set(person, "豬小明");System.out.println(person);} }

運行截圖如下:

下面是關于構造函數的反射:

Person還是與上面的一樣。

import Object.Person;import java.lang.reflect.Constructor;public class Main3 {public static void main(String[] args) throws Exception {Class personClass = Person.class;Constructor constructor = personClass.getConstructor(String.class, Integer.class);System.out.println(constructor);//創建對象Object p = constructor.newInstance("王二麻子", 99);System.out.println(p);System.out.println("----------華麗的分割線----------");Constructor constructor2 = personClass.getConstructor();Object p2 = constructor2.newInstance();System.out.println(p2);} }

程序運行截圖如下:

下面是獲取成員方法的實例。

Person.java

package Object;public class Person {private String name;private Integer age;public String a;protected String b;String c;private String d;public Person(String name, Integer age) {this.name = name;this.age = age;}public Person(){}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", a='" + a + '\'' +", b='" + b + '\'' +", c='" + c + '\'' +", d='" + d + '\'' +'}';}public void eat(){System.out.println("eat... ...");}//帶參數的public void eat(String food){System.out.println("eat... ..." + food);} }

Main4.java

import Object.Person;import java.lang.reflect.Method;public class Main4 {public static void main(String[] args) throws Exception {Class personClass = Person.class;//獲取指定名稱的方法Method eat = personClass.getMethod("eat");Person p = new Person();eat.invoke(p);System.out.println("----------華麗的風格線----------");Method eat1 = personClass.getMethod("eat", String.class);eat1.invoke(p, "西北風");//獲取所有Public修飾的方法Method[] methods = personClass.getMethods();for(Method method : methods){System.out.println(method);String name = method.getName();System.out.println(name);//method.setAccessible(true);}} }

程序運行截圖如下:

下面是關于獲取類名的實例:

Main5.java

import Object.Person;public class Main5 {public static void main(String[] args){Class personClass = Person.class;System.out.println(personClass.getName());} }

程序運行截圖如下:

import Object.Person;public class Main5 {public static void main(String[] args){Class personClass = Person.class;System.out.println(personClass.getName());} }

程序運行截圖如下:

?

?

下面來仿一個案例,像Spring Boot那樣的通過配置application.properties既可以調用相應的類,和函數

這里應用到的就是反射

Main6.java

import Object.Person;import java.io.InputStream; import java.lang.reflect.Method; import java.util.Properties;public class Main6 {public static void main(String[] args) throws Exception {/**** 加載配置文件* 創建Properties對象* 加載配置文件,轉換為集合* 獲取class目錄下的配置文件*/Properties pro = new Properties();ClassLoader classLoader = Person.class.getClassLoader();InputStream resourceAsStream = classLoader.getResourceAsStream("application.properties");pro.load(resourceAsStream);//配置文件中定義的數據String className = pro.getProperty("className");String methodName = pro.getProperty("methodName");//加載該類到內存Class aClass = Class.forName(className);Object o = aClass.newInstance();//獲取方法并執行Method method = aClass.getMethod(methodName);method.invoke(o);} }

通過這種配置文件,即可調用對應的類和方法:

程序運行截圖如下:

源碼打包下載地址:

https://github.com/fengfanchen/Java/tree/master/ReflectDemo

總結

以上是生活随笔為你收集整理的Java工作笔记-对反射的进一步理解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。