Java API中這么解釋Class類:
為了理解RTTI在Java例如何工作,首先必須了解類型信息在運行期間是如何表示的。只要用到一個名為'Class'的特殊形式的對象,這個對象包含了與類有關(guān)的信息(有時候也把它叫作“元類”)。事實上,要用Class類創(chuàng)建屬于某個類的全部“常規(guī)”或“普通”對象。 任何一個作為程序一部分的類,都有一個Class對象。換言之,每次寫一個新類時,同時也會創(chuàng)建一個Class對象(更恰當(dāng)?shù)恼f,是保存在一個完全同名的.class文件中)。在運行期間,一旦程序員想要生成某一個類的對象,用于執(zhí)行程序的Java虛擬機(jī)(JVM)首先就會檢查該類型的Class對象是否已經(jīng)載入。若尚未載入,JVM就會查找同名的.class文件,并將其載入。所以,Java程序啟動時并不是完全載入的,這一點與許多傳統(tǒng)語言不同。一旦該類型的Class對象進(jìn)入內(nèi)存,就用它創(chuàng)建該類型的所有對象。 三、Class動態(tài)加載類的三種方法 (1)類名.Class (2)類型.getClass() (3)Class.forName('類名') (這里的類名表示具體類名,所以要加上包名) 補(bǔ)充: 靜態(tài)加載類和動態(tài)加載類: 編譯時刻加載的類是靜態(tài)加載類,例如用new關(guān)鍵字創(chuàng)建的對象要通過編譯器的靜態(tài)檢查,如果編譯時該類不存在,那么使用該對象的類也無法通過編譯。 運行時刻加載的類是動態(tài)類,在編譯的時候不會進(jìn)行判斷,只有在運行時才會進(jìn)行判斷,假設(shè)該類不存在,在運行時才會報錯。 例如下面的例子: Candy.java文件 package com.test;
public class Candy {
static{
System.out.println('Loading Candy in static block');
}
public static void main(String[] args){
System.out.println('Loading Candy in main method');
}
}
LoadClass.java文件: 運行結(jié)果如下:
Before loding Candy 從程序的輸出結(jié)果來看,用這種方式和new 來創(chuàng)建對象沒什么區(qū)別。其實,二者之間有很大的區(qū)別,用new 關(guān)鍵字創(chuàng)建對象要通過編譯器靜態(tài)檢查,如果編譯時Candy類不存在,那么使用Candy類對象的類LoadClass也無法通過編譯。而forName()方法時動態(tài)加載,即便編譯時Candy類不存在,編譯也是可以通過的,只是在運行時刻會拋出異常。 注意:使用forName()方法存在一個問題,它返回的是一個Class類型,而不是加載的那個類型。所以,無法做出下面的聲明: Candy candy=Class.forName('com.test.Candy'); 也就是說,candy無法直接使用Candy類中定義的方法。解決的辦法是利用反射機(jī)制,不過這比直接用new來創(chuàng)建對象要麻煩得多。所以,用forName()加載對象多用在加載驅(qū)動程序的情況下(例如,加載數(shù)據(jù)庫驅(qū)動)
下面舉個例子熟悉一下Class動態(tài)加載類的方法: package com.baseType;
public class baseClass {
public static void main(String[] args){
Class c1=int.class; //int的類類型
Class c2=String.class; //String類的類類型
Class c3=double.class; //double的類類型
Class c4=Double.class; //Double類的類類型
Class c5=void.class; //關(guān)鍵字void的類類型
//打印類類型的具體名稱
System.out.println(c1.getName()); //int
System.out.println(c2.getName()); //java.lang.String
System.out.println(c3.getName()); //double
System.out.println(c4.getName()); //java.lang.Double
System.out.println(c5.getName()); //void
//不帶包名的類名稱
System.out.println(c2.getSimpleName()); //String
System.out.println(c4.getSimpleName()); //Double
}
} |
|