反射API
Java.lang.Reflect庫
① Class類與Java.lang.Reflect類庫一起對反射的概念進行支持。
② java.lang包下:
a) Class<T>:表示對一個正在運行的Java應用程序中的類和接口,是Reflection的起源。
③ java.lang.reflect包下:
a) Field類:代表類的成員變量(成員變量也稱類的屬性)。
b) Method類:代表類的方法。
c) Constructor類:代表類的構造方法。
d) Array類:提供了動態創建數組,以及訪問數組的元素的靜態方法。
通過反射實例化對象
① 常情況下我們通過new Object來生成一個類的實例,但有時我們沒法直接new,只能通過反射動態生成。
② 實例化無參構造函數的對象,兩種方式:
a) Class.newlnstance();
b) Class.getConstructor(new Class[]{}).newInstance(new Object[]{})
③ 實化帶參構造函數的對象
a) clazz.getConstructor(Class<?>… parameterTypes).newInstance(Object… initargs)
通過反射獲取並調用方法
① 得當前類以及超類的public Method(共有方法)
a) Method[] arrMethod=classType.getMethods();
② 得當前類申明的所有Method
a) Method[] arrMethod=classType.getDeclaredMethods();
③ 獲得當前類以及超類指定的public Method
a) Method method=classType.getMethod(String name,Class<?>… parameterTypes);
④ 得當前類申明的指定的Method
a) Method method=classType. getDeclaredMethods (String name,Class<?>… parameterTypes);
⑤ 通過反射動態運行指定Method
a) Object obj=method.invoke(Object obj,Object… args);
通過反射獲取並調用屬性
① 得當前類以及超類的public Field
a)Field[] arrFields=classType.getField();
② 獲得當前類申明的所有Field
a)Field[] arrFields=classType.getDeclaredFields();
③ 獲得當前類以及超類指定的public Field
a) Field field=classType.getField(String name);
④ 獲得當前類申明的指定的Field
a) Field field=classType.getDeclaredField(String name);
⑤ 通過反射動態設定Field的值
a) field.set(Object obj,Object value);
⑥ 通過反射動態獲取Field的值
a) Object obj=field.get(Object obj);
----------------------------------------------------------------------------------------------------
代碼
創建一個Employee類
1 class Employee { 2 private String name; 3 private int age; 4
5 public Employee() { 6 System.out.println("無參構造方法"); 7 } 8
9 public String getName() { 10 return name; 11 } 12
13 public void setName(String name) { 14 this.name = name; 15 } 16
17 public int getAge() { 18 return age; 19 } 20
21 public void setAge(int age) { 22 this.age = age; 23 } 24
25 public Employee(String name, int age) { 26 super(); 27 this.name = name; 28 this.age = age; 29 } 30
31 @Override 32 public String toString() { 33 return "Employee [name=" + name + ", age=" + age + "]"; 34 } 35
36 private void work() { 37 System.out.println("working..."); 38 } 39
40 }
在主方法中獲取類的屬性及方法:
1 // 獲取Employee這個類所關聯的class對象
2 Class<?> classType = Class.forName("com.iotek.reflection.Employee"); 3 // 通過反射機制來構造一個Employee的實例對象(默認調用無參數的構造方法)
4 Employee employee = (Employee) classType.newInstance(); 5 System.out.println(employee);
輸出結果:
無參構造方法
Employee [name=null, age=0]
1 // 調用指定的構造方法來構造對象(無參構造方法)
2 Constructor<?> constructor = classType.getConstructor(new Class[] {}); 3 Employee employee2 = (Employee)constructor.newInstance(new Object[] {}); 4 System.out.println(employee2);
輸出結果:
無參構造方法
Employee [name=null, age=0]
1 // 調用指定的構造方法來構造對象(帶參構造方法)
2 Constructor<?> constructor2 = classType.getConstructor(new Class[] {String.class, int.class }); 3 Employee employee3 = (Employee) constructor2.newInstance(new Object[] {"zhangsan", 20 }); 4 System.out.println(employee3);
輸出結果:
Employee [name=zhangsan, age=20]
1 // 獲取Class對象所指定的所有方法,包括私有的
2 Method[] methods = classType.getDeclaredMethods(); 3 for (Method method : methods) { 4 System.out.println(method.getName() + "--" + method.getModifiers() 5 + "--" + method.getReturnType()); 6 }
輸出結果:
toString--1--class java.lang.String
getName--1--class java.lang.String
setName--1--void
work--2--void
getAge--1--int
setAge--1—void
1 // 獲取Class對象所指定的方法,包括私有的
2 Method method2 = classType 3 .getDeclaredMethod("toString", new Class[] {}); 4 System.out.println(method2); 5 // 方法的調用
6 String desc = (String) method2.invoke(employee3, new Object[] {}); 7 System.out.println(desc);
輸出結果:
public java.lang.String com.iotek.reflection.Employee.toString()
Employee [name=zhangsan, age=20]
1 // 調用私有方法
2 Method method3 = classType.getDeclaredMethod("work", new Class[] {}); 3 System.out.println(method3.getName()); 4 method3.setAccessible(true);// 設置私有方法可以訪問 5 // 方法的調用
6 method3.invoke(employee3, new Object[] {});
輸出結果:
work
working...
1 // 獲取Class對象所指定的屬性,包括私有的
2 Field field = classType.getDeclaredField("name"); 3 field.setAccessible(true); 4 field.set(employee3, "李四"); 5 System.out.println(field.get(employee3));
輸出結果:
李四
使用反射來創建一維數組:
1 // 創建一個一維數組(String)
2 Class<?> classType = Class.forName("java.lang.String"); 3 Object array = Array.newInstance(classType, 5); 4 Array.set(array, 3, "abc"); 5 System.out.println(Array.get(array, 3));
輸出結果:
abc
使用反射來創建二維數組:
1 // 創建一個二維數組(3行3列)
2 int[] dimens = { 3, 3 }; 3 Object array2 = Array.newInstance(int.class, dimens); 4 Object arrayObj = Array.get(array2, 2);// 獲取第三行(就是一個一維數組)
5 Array.setInt(arrayObj, 2, 10);// 給指定數組位置的元素賦值
6 int [][] arr = (int [][]) array2; 7 System.out.println(arr[2][2]);
輸出結果:
10
反射總結:
① 只要用到反射,先獲得Class對象。
② 沒有方法能獲得當前類的超類的private方法和屬性,你必須通過getSuperclass()找到超類以后再去嘗試獲得。
③ 通常情況下即使是當前類,private屬性或方法也是不能訪問的,你需要設置壓制權限setAccessible(true)來取得private的訪問權。但是,這已經破壞了面向對象的規則,所以除非萬不得已,請盡量少用。