目錄
一、概述
二、class類:
1、獲取類的字節碼文件:
(1)方式一:直接通過一個class的靜態變量class獲取
(2)方式二:如果知道一個class的完整類名,可以通過靜態方法Class.forName()獲取
(3)方式三:通過具體對象的getClass方法獲取
2、Class.newInstance()通過字節碼文件對象創建具體類的實例:(此類中必須有無參構造方法)
3、Class常用的方法:
三、調用構造方法
1、getConstructors() 獲取所有被public修飾的構造方法
2、getDeclaredConstructors()獲取所有的構造方法(不受訪問修飾符限制)
3、getConstructor()獲取某個指定的被public修飾的構造方法
4、getDeclaredConstructor 獲取指定的某個構造方法 可以給泛型
5、解剖構造方法
(1)getModifiers():獲取構造方法的權限修飾符:包訪問修飾符-0 public-1 private-2 protected-4
(2)setAccessible(true):臨時取消權限校驗符
四、獲取繼承關系:
1、getSuperclass():獲取該類繼承的類,返回Class對象
2、getlnterfaces():獲取該類實現的所有接口,返回Class 型數組
五、訪問字段
1、獲取成員變量:
(1)getFields()獲取所有的被public修飾的成員變量(包含父類的成員變量)
(2)getDeclaredFields()獲取所有本類中的成員變量(包含私有的等)
(3)getField()獲取本類中或者父類中的某個被public修飾的成員變量
(4)getDeclaredField()獲取本類中的某個成員變量
2、解剖成員變量:
(1)getModifiers():獲取權限修飾符
(2)getType():獲取數據類型
(3)getName():獲取變量名
3、應用:
(1)get(Object? ?o):獲取對象中此成員變量的值:
(2)set(Object? ?o, Object? Value)設置對象中此成員變量的值
(3)注意事項:靜態成員變量不依賴于對象,靜態成員變量共享一片空間,所以可以不傳入對象,直接修改修改
一、概述
? ?Java
反射機制是 Java
語言的一個重要特性。在學習 Java
反射機制前,大家應該先了解兩個概念:編譯期和運行期。
編譯期:是指把源碼交給編譯器編譯成計算機可以執行的文件的過程。在 Java
中也就是把 Java
代碼編成 class
文件的過程。編譯期只是做了一些翻譯功能,并沒有把代碼放在內存中運行起來,而只是把代碼當成文本進行操作。比如:檢查語法錯誤。
運行期:是把編譯后的文件交給計算機執行,直到程序運行結束。所謂運行期就把在磁盤中的代碼放到內存中執行起來。
? ? ? ?Java 反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱為 Java
語言的反射機制。簡單來說,反射機制指的是程序在運行時能夠獲取自身的信息。在 Java
中,只要給定類的名字,就可以通過反射機制來獲得類的所有信息。
Java
反射機制在服務器程序和中間件程序中得到了廣泛運用。在服務器端,往往需要根據客戶的請求,動態調用某一個對象的特定方法或者為屬性賦值。例如:在主流的 ORM
框架的實現中,運用 Java
反射機制可以讀取任意一個 JavaBean
的所有屬性,或者給這些屬性賦值。
Java
反射機制主要提供了以下功能,這些功能都位于java.lang.reflect
包。
- 在運行時判斷任意一個對象所屬的類。
- 在運行時構造任意一個類的對象。
- 在運行時判斷任意一個類所具有的成員變量和方法。
- 在運行時調用任意一個對象的方法。
- 生成動態代理。
二、class類:
? ? ? 要想知道一個類的屬性和方法,必須先獲取到該類的字節碼文件對象。獲取類的信息時,使用的就是 Class
類中的方法。所以先要獲取到每一個字節碼文件(.class
)對應的 Class
類型的對象.class
(包括interface
)的本質是數據類型(Type
)。class
是由JVM
在執行過程中動態加載的。JVM
在第一次讀取到一種class
類型時,將其加載進內存。每加載一種class
,JVM
就為其創建一個Class
類型的實例,并關聯起來。
注意:這里的Class
類型是一個名叫Class
的class。
1、獲取類的字節碼文件:
(1)方式一:直接通過一個class的靜態變量class獲取
//方式一:直接通過一個class的靜態變量class獲取Class clazz1=Person.class;System.out.println(clazz1);
(2)方式二:如果知道一個class的完整類名,可以通過靜態方法Class.forName()獲取
//方式二:如果知道一個class的完整類名,可以通過靜態方法Class.forName()獲取Class clazz2=Class.forName("com.yuan.reflection.Person");System.out.println(clazz2);
(3)方式三:通過具體對象的getClass方法獲取
//方式三:通過具體對象的getClass方法獲取Person p1=new Person();Class clazz3=p1.getClass();System.out.println(clazz3);
2、Class.newInstance()通過字節碼文件對象創建具體類的實例:(此類中必須有無參構造方法)
//通過Class.newInstance()可以創建類的實例,要求實例必須要有公共的無參構造方法,否則報錯Object p2 = clazz1.newInstance();System.out.println(p2);
3、Class常用的方法:
類型 | 訪問方法 | 返回值類型 | 說明 |
包路徑 | getPackage() | Package 對象 | 獲取該類的存放路徑 |
類名稱 | getName() | String 對象 | 獲取該類的名稱 |
繼承類 | getSuperclass() | Class 對象 | 獲取該類繼承的類 |
實現接口 | getlnterfaces() | Class 型數組 | 獲取該類實現的所有接口 |
構造方法 | getConstructors() | Constructor 型數組 | 獲取所有權限為 public 的構造方法 |
getDeclaredContruectors() | Constructor 對象 | 獲取當前對象的所有構造方法 | |
方法 | getMethods() | Methods 型數組 | 獲取所有權限為 public 的方法 |
getDeclaredMethods() | Methods 對象 | 獲取當前對象的所有方法 | |
成員變量 | getFields() | Field 型數組 | 獲取所有權限為 public 的成員變量 |
getDeclareFileds() | Field 對象 | 獲取當前對象的所有成員變量 |
三、調用構造方法
1、getConstructors() 獲取所有被public修飾的構造方法
2、getDeclaredConstructors()獲取所有的構造方法(不受訪問修飾符限制)
3、getConstructor()獲取某個指定的被public修飾的構造方法
4、getDeclaredConstructor 獲取指定的某個構造方法 可以給泛型
5、解剖構造方法
(1)getModifiers():獲取構造方法的權限修飾符:包訪問修飾符-0 public-1 private-2 protected-4
(2)setAccessible(true):臨時取消權限校驗符
public class Demo04 {public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {//1、獲取類的字節碼文件對象Class<Person> clazz = Person.class;//2、獲取構造方法//getConstructors() 獲取所有被public修飾的構造方法
// Constructor[] cons = clazz.getConstructors();
// for (Constructor con:cons) {
// System.out.println(con);
// }//getDeclaredConstructors()獲取所有的構造方法(不受訪問修飾符限制)Constructor[] cons = clazz.getDeclaredConstructors();for (Constructor con:cons) {System.out.println(con);}//getConstructor()獲取某個指定的被public修飾的構造方法Constructor con = clazz.getConstructor();System.out.println(con);//getDeclaredConstructor 獲取指定的某個構造方法 可以給泛型Constructor<Person> con1=clazz.getDeclaredConstructor(String.class,int.class);System.out.println(con1);//3、解剖//包-0 public-1 private-2 protected-4int modifier = con1.getModifiers();System.out.println(modifier);System.out.println("權限修飾符是否是公共的"+Modifier.isPublic(modifier));Parameter[] parameters = con1.getParameters();for (Parameter p:parameters) {System.out.println(p.getType()+"_"+p.getName());}//4、實例化對象con1.setAccessible(true);//臨時取消權限校驗符Person p1 = con1.newInstance("張三", 13);//注意構造方法要為public,不是公共的需要設置取消臨時校驗符System.out.println(p1);}
}
四、獲取繼承關系:
1、getSuperclass():獲取該類繼承的類,返回Class對象
2、getlnterfaces():獲取該類實現的所有接口,返回Class 型數組
public class Demo03 {public static void main(String[] args) {Class clazz = Person.class;//包路徑 getPackage() Package對象獲取該類的存放路徑Package pac = clazz.getPackage();System.out.println(pac);//類名稱 getName() String對象 獲取該類的名稱String strName = clazz.getName();System.out.println(strName);//繼承類getSuperclass() Class對象 獲取該類繼承的類Class supclasss = clazz.getSuperclass();System.out.println(supclasss);//實現的接口Class[] cles = clazz.getInterfaces();System.out.println(Arrays.toString(cles));}
}
五、訪問字段
1、獲取成員變量:
(1)getFields()獲取所有的被public修飾的成員變量(包含父類的成員變量)
(2)getDeclaredFields()獲取所有本類中的成員變量(包含私有的等)
(3)getField()獲取本類中或者父類中的某個被public修飾的成員變量
(4)getDeclaredField()獲取本類中的某個成員變量
Class<Dog> clazz = Dog.class;//2、獲取成員變量
// //getFields()獲取所有的被public修飾的成員變量(包含父類的成員變量)Field[] fields = clazz.getFields();for (Field f:fields) {System.out.println(f);}//getDeclaredFields()獲取所有本類中的成員變量(包含私有的等)Field[] fields2 = clazz.getDeclaredFields();for (Field f:fields2) {System.out.println(f);}//getField()獲取本類中或者父類中的某個被public修飾的成員變量Field field = clazz.getField("type");System.out.println(field);//getDeclaredField()獲取本類中的某個成員變量Field field = clazz.getDeclaredField("color");System.out.println(field);
2、解剖成員變量:
(1)getModifiers():獲取權限修飾符
(2)getType():獲取數據類型
(3)getName():獲取變量名
//獲取權限修飾符int modifier = field.getModifiers();System.out.println("權限修飾符為:"+modifier);//獲取數據類型Class typeClass = field.getType();System.out.println("數據類型為:"+typeClass);//獲取變量名String name = field.getName();System.out.println("此成員變量的變量名為:"+name);
3、應用:
(1)get(Object? ?o):獲取對象中此成員變量的值:
(2)set(Object? ?o, Object? Value)設置對象中此成員變量的值
(3)注意事項:靜態成員變量不依賴于對象,靜態成員變量共享一片空間,所以可以不傳入對象,直接修改修改
Dog d2=new Dog();Dog d1=new Dog("花花",5,"田園犬",20.0,25,"花色");
// field.setAccessible(true);//臨時取消校驗符
// //獲取d1對象中此成員變量的值
// Object obj = field.get(d1);
// System.out.println("獲取到成員變量type對應對象d1的值"+obj);
// //設置對象d1中此成員變量的值為黑白
// field.set(d1,"黑白");
// System.out.println(d1);//靜態成員變量不依賴于對象field.setAccessible(true);//臨時取消校驗符//獲取靜態成員變量,不依賴于對象二存在,所以獲取此成員變量的值時,可以不傳對象Object obj = field.get(null);System.out.println("獲取到成員變量type對應對象d1的值"+obj);//設置成員變量值,靜態成員變量共享一片空間,所以可以修改field.set(null,"黑白");System.out.println(d1);System.out.println(d2);
public class Animal {public String name;private int age;public Animal(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Animal{" +"name='" + name + '\'' +", age=" + age +'}';}
}
package com.yuan.reflection;public class Dog extends Animal{public String type;protected double weight;int height;public static String color;public Dog() {super("小白",23);}public Dog(String name, int age, String type, double weight, int height, String color) {super(name, age);this.type=type;this.weight=weight;this.height=height;this.color=color;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +", type='" + type + '\'' +", weight=" + weight +", height=" + height +", color=" + color +'}';}
}