Java之反射(01)
本文的主要資料來源於《Thinking in Java》以及尚矽谷宋巨集康老師的視訊課程,附上視訊連結:https://www.bilibili.com/video/BV1Kb411W75N,有興趣的讀者可以自行B站前往觀看
1.反射的概念
反射就是在編譯的時候將類的結構儲存到方法區中,只有在執行時才動態地獲取類的物件、屬性、方法
2.為什麼要使用反射
一般的,我們獲取某個類的物件最常用的方式是使用new()
關鍵字,來創造一個具體的物件,而這個物件是在編譯期間就已經建立好了的。那麼為什麼需要在執行期也建立物件呢,這裡就涉及到另一個Java特性——泛型。
3.反射的執行原理
Java虛擬機器在讀取某個類的檔案位元組碼(.class檔案)的時候,會將這個類載入到JVM之中,併產生一個Class物件,而且只會產生一個,這個Class物件包含了該類的屬性、方法、建構函式、包等各種資訊,在執行時期間,外部可以通過某些手段動態地獲取該類的這些資訊,具體類的載入流程參見《深入理解Java虛擬機器》。
圖1 Java中正常建立物件和反射的流程
4.反射的使用
4.1獲取Class類的三種方式
以Apple類為例
class Apple {
public String name;
public Integer type;
public Apple(){}
public Apple(String name, Integer type) {
this.name = name;
this.type = type;
}
}
在Test類中使Apple類
public static void main(String[] args) throws ClassNotFoundException { /* 1.使用Class.forName方法 */ Class<?> clazz = Class.forName("com.kundi.loader.Apple"); /* 2.使用類的.class屬性 */ Class<Apple> aClass = Apple.class; /* 3.使用物件的.getClass方法 */ Apple apple = new Apple(); Class<? extends Apple> aClass1 = apple.getClass(); }
上面的<?>
屬於泛型的範疇,看不懂的可以忽略,重點是Class類。不難看出,上面三種建立Class物件的三種方式中,第一種是相對方便,也是最常用的,因為可以根據引數字串確定所要建立的Class物件;而第二中則需要提前知道類名,缺少靈活性;第三種就更不靈活了,都已經獲取了物件了,再獲取Class物件意義不大,除非是要呼叫某些訪問修飾符為private或其他訪問不到的型別。
4.2 Class類的使用
那麼,拿到了Class類能夠幹什麼用呢?是否真如想象中的那麼靈活?關於反射類的包,均存在於JDK的java.lang.reflect
包下,裡面的API也很多,但並不是每一樣都能用得上,典型的用的比較多的有下面這些:
(1)通過反射建立類的物件
Apple apple1= (Apple)clazz.newInstance();
注意:這裡要將Object類強轉為Apple類,而且使用Class.newInstance()使用的是預設無參構造方法
(2)
Constructor<? extends Apple> constructor = aClass1.getConstructor(String.class, String.class);
Apple apple2 = constructor.newInstance("紅富士", "紅蘋果");
這裡可以獲取有參的構造方法,然後建立物件
參考文章
https://blog.csdn.net/grandgrandpa/article/details/84832343
https://www.cnblogs.com/chanshuyi/p/head_first_of_reflection.html