加拿大皇家銀行:蘋果或購買比特幣,該公司應建立加密交易所
阿新 • • 發佈:2021-02-11
技術標籤:Java基礎
學習目標
掌握通過反射獲得類名
掌握通過反射例項化其他類的物件
掌握通過反射獲得其他類中的全部建構函式
掌握獲得其他類中的全部屬性
掌握呼叫其他類中的方法
掌握通過反射操作屬性
掌握通過反射取得陣列的資訊
Java 語言的反射機制
- 在Java執行時環境中,對於任意一個類物件,能否知道這個類有哪些屬性和方法?對於任意一個物件,能否呼叫它的任意一個方法?答案是肯定的。這種動態獲取類的資訊以及動態呼叫物件的方法的功能來自於Java 語言的反射(Reflection)機制。
- Java 反射機制主要提供了以下功能
在執行時判斷任意一個物件所屬的類。
在執行時構造任意一個類的物件。
在執行時判斷任意一個類所具有的成員變數和方法。
在執行時呼叫任意一個物件的方法
- Reflection 是Java被視為動態(或準動態)語言的一個關鍵性質。這個機制允許程式在執行時透過Reflection APIs取得任何一個已知名稱的class的內部資訊,包括其modifiers(諸如public, static 等許可權)、superclass(例如Object)、實現interfaces(例如Serializable),也包括fields(屬性)和methods(方法)的所有資訊,並可於執行時改變fields內容或呼叫methods
- 一般而言,開發者社群說到動態語言,大致認同的一個定義是:“程式執行時,允許改變程式結構或變數型別,這種語言稱為動態語言”。從這個觀點看,Perl,Python,Ruby是動態語言,C++,Java,C#不是動態語言
- 儘管在這樣的定義與分類下Java不是動態語言,它卻有著一個非常突出的動態相關機制:Reflection。這個字的意思是“反射、映象、倒影”,用在Java身上指的是我們可以於執行時載入、探知、使用編譯期間完全未知的classes。換句話說,Java程式可以載入一個執行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其物件實體、或對其fields設值、或喚起其methods。這種“看透class”的能力(the ability of the program to examine itself)被稱為introspection(內省、內觀、反省)。Reflection和introspection是常被並提的兩個術語
Java Reflection API 簡介
- 在JDK中,主要由以下類來實現Java反射機制,這些類(除了Class類在java.lang包),其他類都位於java.lang.reflect包中
Class類:代表一個類。
Field 類:代表類的成員變數(成員變數也稱為類的屬性)。
Method類:代表類的方法。
Constructor 類:代表類的構造方法。
Array類:提供了動態建立陣列,以及訪問陣列的元素的靜態方法 - 在java.lang.Object 類中定義了getClass()方法,因此對於任意一個Java物件,都可以通過此方法獲得物件的型別。Class類是Reflection API 中的核心類,它有以下方法
getName():獲得類的完整名字。
getFields():獲得類的public型別的屬性。
getDeclaredFields():獲得類的所有屬性。
getMethods():獲得類的public型別的方法。
getDeclaredMethods():獲得類的所有方法。 - getMethod(String name, Class[] parameterTypes):獲得類的特定方法,name引數指定方法的名字,parameterTypes 引數指定方法的引數型別。
- getConstructors():獲得類的public型別的構造方法。
- getConstructor(Class[] parameterTypes):獲得類的特定構造方法,parameterTypes 引數指定構造方法的引數型別。
- newInstance():通過類的不帶引數的構造方法建立這個類的一個物件。
- (2)通過預設構造方法建立一個新物件
Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
以上程式碼先呼叫Class類的getConstructor()方法獲得一個Constructor 物件,它代表預設的構造方法,然後呼叫Constructor物件的newInstance()方法構造一個例項。 - (3)獲得物件的所有屬性:
Field fields[]=classType.getDeclaredFields();
Class 類的getDeclaredFields()方法返回類的所有屬性,包括public、protected、預設和private訪問級別的屬性
例項方法
public static void main(String[] args) {
try {
//第一種方法
//根據類名.class屬性獲取該類的位元組碼類物件,該類物件是在虛擬機器載入類時建立
Class<Student> s1 = Student.class;
Class<Student> s2 = Student.class;
//第二種方法
//呼叫class的靜態方法,通過類的完整名稱字串forName,獲取Class例項。?是不知道那個類
Class<?> s3 = Class.forName("com.entor.test.demo46_反射.test.Student");
//第三種方法
Student s = new Student();
Class<? extends Student> s4 = s.getClass();
//獲取該類中所有的公共屬性
System.out.println("--------------------所有公共屬性------------------");
Field[] fields = s1.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
//獲取類中的所有屬性
System.out.println("--------------------所有屬性------------------");
Field[] fields1 = s1.getDeclaredFields();
Arrays.stream(fields1).forEach(ss -> {
System.out.print("屬性修飾詞 "+ Modifier.toString(ss.getModifiers()));
System.out.print("屬性型別 "+ss.getType().getSimpleName());
System.out.print("屬性名稱 "+ss.getName());
System.out.println("\n");
});
//獲取類中所有的公共方法
System.out.println("--------------------所有公共方法------------------");
Method[] methods = s1.getMethods();
Arrays.stream(methods).forEach(ss -> {
System.out.print("屬性修飾詞 "+ Modifier.toString(ss.getModifiers()));
System.out.print("屬性型別 "+ss.getReturnType().getSimpleName());
System.out.print("屬性名稱 "+ss.getName());
Class<?>[] parameterTypes = ss.getParameterTypes();
System.out.print("--------------引數列表--------------");
Arrays.stream(parameterTypes).forEach(sss->{
System.out.print("屬性名稱 "+sss.getSimpleName());
});
System.out.println("\n");
});
//獲取類中所有的方法
System.out.println("--------------------所有方法------------------");
Method[] methods1 = s1.getDeclaredMethods();
Arrays.stream(methods1).forEach(ss -> {
System.out.print("屬性修飾詞 "+ Modifier.toString(ss.getModifiers()));
System.out.print("屬性型別 "+ss.getReturnType().getSimpleName());
System.out.print("屬性名稱 "+ss.getName());
System.out.println("\n");
});
System.out.println(s1 == s2);//true 單例模式
System.out.println(s1 == s3);//true 單例模式
System.out.println(s1 == s4);//true 單例模式
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}