1. 程式人生 > >Java基礎 | 反射(學習筆記)

Java基礎 | 反射(學習筆記)

文章目錄

1. 概述

Reflection(反射)是Java被視為動態語言的關鍵,反射機制允許程式在執行期藉助於Reflection API

取得任何類的內部資訊,並能直接操作任何物件的內部屬性和方法。

為什麼要使用反射?

反射的主要作用是在執行時獲取類資訊和呼叫類方法,如果有些類的的資訊在編譯階段是不確定,需要到執行時才確定的情況時,這個時候就需要使用到類的反射

Java反射機制主要提供以下功能:

  • 在執行時判斷任意一個物件所屬的類
  • 在執行時構造任意一個類的物件
  • 在執行時獲取任意一個類所具有的成員變數和方法
  • 在執行時呼叫任意一個物件的成員變數和方法
  • 生成動態代理

2. 理解Class類並例項化Class類物件

2.1 理解Class類

在《Java程式設計思想》中,作者告訴我們“萬事萬物皆是物件

”,而這也是Java之中面向物件程式設計的核心思想。
當我們需要一個物件的時候,我們的第一想法就是先寫一個類,然後new一個物件出來,但是我們有沒有考慮過,既然說“萬事萬物皆是物件”,難道在這裡類就是例外了嗎?它是不是物件呢?

答案是的,我們平時寫的類是java.lang.Class類的例項物件

Object類中定義了以下的方法,此方法將被所有子類繼承:
public final Class getClass()

以上的方法返回值的型別是一個Class類,此類是Java反射的源頭,實際上所謂反射從程式的執行結果來看也很好理解,即:可以通過物件反射求出類的名稱。

###執行時類的由來
建立一個類—>通過編譯(javax.exe),生成對應的 .class 檔案—> 通過載入(JVM的類載入器完成的java.exe)
此.class 檔案載入到記憶體以後,就是一個執行時類,存在快取區,那麼這個執行時類本身就是一個Class的例項

  • Class本身也是一個類
  • Class 物件只能由系統建立物件
  • 一個類在 JVM 中只會有一個Class例項
  • 一個Class物件對應的是一個載入到JVM中的一個.class檔案
  • 每個類的例項都會記得自己是由哪個 Class 例項所生成
  • 通過Class可以完整地得到一個類中的完整結構

類的載入過程

當程式主動使用某個類時,如果該類還未被載入到記憶體中,則系統會通過如下三個步驟來對該類進行初始化

  1. 類的載入:將類的class檔案讀入記憶體,併為之建立一個java.lang.Class物件。此過程由類載入器完成
  2. 類的連線: 將類的二進位制資料合併到JRE中
  3. 類的初始化:JVM負責對類進行初始化

2.2 獲取Class物件方法(4種)

  • 通過執行時類本身的 .class 屬性
  • 通過執行時類的物件,呼叫getClass(),返回其執行時類
  • 通過 Class 的靜態方法獲取
  • 通過類的載入器
Class c1 = 類名.class;

Class c2 = 例項物件.getClass();

Class c3 = Class.forName("com.類名");

ClassLoader classLoader = this.getClass().getClassLoader();
Class c4 = classLoader.loadClass("com.類名");

3. 執行時建立類物件並獲取類的完整結構

3.1 建立執行時類的物件

  • 呼叫Class物件的newInstance()方法
Class cla = Person.class;
Person p =   (Person)cla.newInstance(); //呼叫此方法,必須Person類需要有對應的構造方法(如空參構造器)
System.out.println(p);

4. 通過反射呼叫類的指定方法、指定屬性

這裡只是舉有關於屬性和方法的一個例子,具體的沒有記錄

//1.通過反射呼叫執行時類的指定的屬性、
Field f1 = cla.getField("name");
f1.set(p, "Rose");
System.out.println(p);

//2.通過反射呼叫執行時類的指定的方法
Method m1 = cla.getMethod("show");
m1.invoke(p);

5. 動態代理