基礎 | Class類詳解
Object類中的getClass()方法即返回一個Class型別的例項,那麼 「Class類到底是什麼?從何而來?又有什麼作用呢?」
參考答案
Class類是什麼?
先來簡單瞭解一下Java虛擬機器中類的載入過程:
「載入」階段是「類載入」過程的第一個階段,虛擬機器需要完成以下三件事情:
- 通過一個類的全限定名來獲取定義此類的二進位制位元組流(.class檔案即儲存著類的二進位制資料)。
- 將該位元組流所代表的靜態儲存結構轉化為方法區的執行時資料結構。
- 在Java堆中生成一個代表該類的java.lang.Class物件,作為方法區中該資料結構的訪問入口。
也就是說,Class是一個儲存著執行時類所有資訊的類,即在程式執行時跟蹤類且掌握著類的全部資訊,故其也被稱為反射的源頭(有點兒小抽象)。
如何獲取Class類物件?
共有四種方式來獲取Class類的例項,如下:
@Test
// 需要提供異常處理
public void test() throws ClassNotFoundException{
//1.通過執行時類的.class屬性獲取
Class<Person> clazz1 = Person.class;
System.out.println(clazz1);
//2.通過執行時類的物件獲取
Person p = new Person();
Class clazz2 = p.getClass();
System.out.println(clazz2.getName());
//3.通過Class類的靜態方法獲取
String className = "com.whutqbchen.java.Person";
Class clazz3 = Class.forName(className);
System.out.println(clazz3);
//4.通過類的載入器獲取
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass(className);
System.out.println(clazz4.getName());
}
提示:在啟動時,包含main方法的類被載入。它會載入所有需要的類。這些被加栽的類又要載入它們需要的類,以此類推。對於一個大型的應用程式來說,這將會消耗很多時間,使用者會因此感到不耐煩。可以使用下面這個技巧給使用者一種啟動速度比較快的幻覺。不過,要確保包含main方法的類沒有顯式地引用其他的類。首先,顯示一個啟動畫面;然後,通過呼叫Class.forName手工地載入其他的類。
Class類的例項可以做什麼?
獲取到執行時類的Class例項後,通過Class類的例項可以:
- 通過newInstance()方法建立對應執行類的物件。
- 獲取其對應類的完整結構,如構造器、屬性、方法、內部類、父類、所在的包、異常和註解等。
- 呼叫對應的執行時類的指定結構,如屬性、方法和構造器。
- 反射的應用,即動態代理(又挖一坑)。
所以說,Class類是反射的源頭,有一種「Class在手天下我有」的既視感。
這也是Java中「反射」技術的主要內容。
注意事項:
請注意,一個Class物件實際上表示的是一個型別,而這個型別未必一定是一種類。例如,int不是類,但int.class是一個Class型別的物件。
另外,呼叫Class類例項的newInstance()方法動態建立類物件時,需要對應的執行時類中有空參的構造器,這個細節本人在面試Synopsys的時候被問到過。
原始碼閱讀
通過Class類的例項獲取執行時類的所有描述資訊的程式碼較長,在此僅給出對應的方法描述,如下:
推薦閱讀
歡迎關注
Java名企面試吧,每天10點24分,我們不見不散!
丙子先生的宗旨是,每天以短篇幅講高頻面試題,不增加太多負擔,但需要持之以恆。
能力有限,歡迎指教!