什么是反射
Java的反射是指程式在運行期可以拿到一個物件的所有資訊,
一般情況下,如果我們要呼叫一個物件的方法,或者訪問一個物件的欄位,通常會傳入物件實體,
Class類
java除了基本的型別(String,int.....)全部是class型別
class是由JVM在執行程序中動態加載的,JVM在第一次讀取到一種class型別時,將其加載進記憶體,每加載一種class,JVM就為其創建一個Class型別的實體,并關聯起來,注意:這里的Class型別是一個名叫Class的class,
由于JVM為每個加載的class創建了對應的Class實體,并在實體中保存了該class的所有資訊,包括類名、包名、父類、實作的介面、所有方法、欄位等,因此,如果獲取了某個Class實體,我們就可以通過這個Class實體獲取到該實體對應的class的所有資訊,
//通過一個class的靜態變數class獲取
Class cls = String.class;
//知道一個class的完整類名,可以通過靜態方法Class.forName()獲取
Class cls = Class.forName("java.lang.String");
//有一個實體變數,可以通過該實體變數提供的getClass()方法獲取
String str = "Hello";
Class cls = str.getClass();
//獲取到了一個Class實體,我們就可以通過該Class實體來創建對應型別的實體,但只能呼叫public的無引數構造方法
// 獲取String的Class實體:
Class cls = String.class;
// 創建一個String實體:
String s = (String) cls.newInstance();
獲取/設定欄位(屬性)
只要獲取了任何一個實體的Class實體,就可以獲取它的一切資訊,
Field物件包含了一個欄位的所有資訊
---getName():回傳欄位名稱,例如,"name";
---getType():回傳欄位型別,也是一個Class實體
Field getField(name)//根據欄位名獲取某個public的field(包括父類)
Field getDeclaredField(name)//根據欄位名獲取當前類的某個field(不包括父類)
Field[] getFields()//獲取所有public的field(包括父類)
Field[] getDeclaredFields()//獲取當前類的所有field(不包括父類)
public class Test {
public static void main(String[] args) throws Exception {
Object p = new Person("Xiao Hua");
Class cla = p.getClass();
Field f = cla.getDeclaredField("name");
f.setAccessible(true);//一律允許訪問該欄位,否則private不能訪問的
Object value = f.get(p);
System.out.println(value); // "Xiao Hua"
f.set(p, "Xiao Hong");
System.out.println(p.getName()); // "Xiao Hong"
}
}
class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
呼叫方法
可以通過Class實體獲取所有Method(方法封裝成的物件)資訊,Class類提供了以下幾個方法來獲取Method:
Method getMethod(name, Class...):獲取某個public的Method(包括父類)
Method getDeclaredMethod(name, Class...):獲取當前類的某個Method(不包括父類)
Method[] getMethods():獲取所有public的Method(包括父類)
Method[] getDeclaredMethods():獲取當前類的所有Method(不包括父類)
呼叫方法,對Method實體呼叫invoke就相當于呼叫該方法,invoke的第一個引數是物件實體(靜態方法傳null),即在哪個實體上呼叫該方法,后面的可變引數要與方法引數一致,通過Method.setAccessible(true)也可以允許呼叫
非public方法
public class Test {
public static void main(String[] args) throws Exception {
String s = "Hello world";
// 獲取String substring(int)方法,引數為int:
Method m = String.class.getMethod("substring", int.class);
//m.setAccessible(true);
// 在s物件上呼叫該方法并獲取結果:
String r = (String) m.invoke(s, 6);
// 列印呼叫結果:
System.out.println(r);
}
}
呼叫構造方法
---Person p = Person.class.newInstance();
局限是,它只能呼叫該類的public無引數構造方法,
如果構造方法帶有引數,或者不是public,就無法直接通過Class.newInstance()來呼叫,
---為了呼叫任意的構造方法,反射API提供了Constructor物件,
它包含一個構造方法的所有資訊,可以創建一個實體,
public class Test {
public static void main(String[] args) throws Exception {
// 獲取構造方法Integer(int):
Constructor cons1 = Integer.class.getConstructor(int.class);
// 呼叫構造方法:
Integer n1 = (Integer) cons1.newInstance(123);
System.out.println(n1);
// 獲取構造方法Integer(String)
Constructor cons2 = Integer.class.getConstructor(String.class);
Integer n2 = (Integer) cons2.newInstance("456");
System.out.println(n2);
}
}
參考:https://www.liaoxuefeng.com
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/297687.html
標籤:其他
上一篇:上報系統對比,定位跟權限
