1. 程式人生 > 實用技巧 >Java之反射(01)

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