Java高階之反射
阿新 • • 發佈:2019-01-28
反射
1 為什麼學習反射
剛開始接觸反射,是不是覺得很高大上,事實上也確實如此。筆者基本也是通過看視訊和查閱資料學習的,到現在也才是剛剛入門而已。 如果世界沒有反射,即使有陽光,有色彩,那麼我們還是不能看到這個美麗的世界。反射在Java中的地位也是這樣的重要,如果Java沒有反射,那麼Java現在的地位是非常堪憂的的,因為他很多技術都是基於反射來實現的。 初學者一開始就接觸Java反射,那是很難接收和理解的。一開始,筆者在學習Java的時候,自動就跳過了反射這一章節,因為在實際寫程式碼的過程中,看起來我們幾乎不使用到反射的知識。那不好意思,你的想法從一開始就錯了,以為你一開始接觸到的Eclipse、Myeclipse和Idea本身就使用到了Java反射的知識2 反射是什麼
反射的概念用官方的話來解釋太麻煩了,通俗來講,反射就是來操作Java類的一種機制,通過反射可以操作Java中的位元組碼檔案。 大家接觸過Java的都知道,Java最終執行的是位元組碼檔案,而不是.java檔案。 反射的核心類是Class類3 反射的基本操作
獲取Class位元組碼物件 Class類是用來操作位元組碼檔案的,那麼第一步就是如何獲取位元組碼檔案。前面也說過,Class是類的類模板,所以說它不屬於任何一個物件,只是一個類的模板。 獲取位元組碼物件有三種方式:類.class、Class.forName(路徑)、物件.getClass()。千萬要記住,獲取的是類的模板,所以只有一份System.out.println("物件.getClass()獲取位元組碼檔案的地址:" + student.getClass().hashCode());
System.out.println("Class.forName(路徑)獲取位元組碼檔案的地址:" + Class.forName("base.Student").hashCode());
System.out.println("類名.class獲取位元組碼檔案的地址:" + Student.class.hashCode());
獲取類實現的介面和類的父類位元組碼物件我們都知道Java是單繼承多實現,所以獲取介面的時候是獲取介面陣列。
System.out.println("getSuperclass()方法獲取父類的類模板的地址:" + Student.class.getSuperclass().hashCode());
System.out.println("getInterfaces()獲取的介面陣列,其長度為:" + Student.class.getInterfaces().length);
獲取類的構造方法並建立一個物件
我們剛開始接觸Java的封裝思想時,知道可以用new關鍵字建立物件,而且可以有預設的無參即有參構造方法。new的實質實現就是用Java反射來實現的,即獲取構造方法和建立物件兩個步驟,當然構造方法有時候Java虛擬機器會自動幫我們建立無參的預設構造方法。
這裡就會涉及到過載的問題了,因為建構函式在一個類中可以有多個,既可以獲取所有的構造方法陣列,也可以獲取某一個指定的構造方法。//預設無參構造方法
Object object = clazz.newInstance();
Constructor con2 = clazz.getConstructor(String.class, String.class, String.class, Integer.class);
Object object2 = con2.newInstance("Jack", "男", "大二", 22);
通過位元組碼物件建立類的一個物件並執行其中的方法方法的執行我們通常是用“.”來呼叫某個物件的方法的,其實也是通過Java反射來實現的。 方法都有過載,所以我們可以獲取方法陣列或者是某一個特定的方法。首先是獲取方法模板,然後指定該方法時屬於哪個物件的。
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
System.out.println(method.getName());
}
Method setAge = clazz.getMethod("setAge", Integer.class, String.class);
setAge.invoke(object2, 23, "Mary");
4 反射的使用小案例
如果接觸過Java資料庫程式設計,那麼應該都知道需要載入資料庫驅動,這一步就是用到了反射,而如果接觸過Spring的人來說,對於IOC也不是很陌生了。 IOC,不理解沒關係,這裡簡單說說就明白了。IOC說通俗點,A類中需要B類,那麼IOC就是將B類的建立交給第三方來建立,然後再注入到A類中,這樣就不需要在A類中用new關鍵字來直接建立物件了。這個第三方一般是通過配置檔案來設定。 配置檔案.properties的內容存放類的路徑:##key=value##
className=java.util.ArrayList
通過Java的IO流來讀取配置檔案的內容,然後動態地建立物件。這裡使用到Java自帶的一種類Properties類,專門用來處理.properties檔案中的鍵和值。public static void main(String[] args) {
InputStream in = null;
try {
//讀取檔案
in = new FileInputStream("config/config-ioc.properties");
//獲取值
Properties properties = new Properties();
properties.load(in);
String value = properties.getProperty("className");
System.out.println("值:" + value);
//反射建立物件
Class clazz = Class.forName(value);
ArrayList list = (ArrayList) clazz.newInstance();
list.add("Jack");
list.add("Rose");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}