運行時類型辨識(RTTI, Run-Time Type Identification)是Java中非常有用的機制,在Java執行時,RTTI維護類別的相關資訊。
多態(polymorphism)是基於RTTI實現的。 RTTI的功能主要是由Class類別實現的。
Class類
Class類別是"類別的類別"(class of classes)。如果說類別是物件的抽象和集合的話,那麼Class類別就是對類別的抽象和集合。
每一個Class類別的物件都代表一個其他的類別。例如下面的程式中,Class類的物件c1代表了Human類,c2代表了Woman類。
複製代碼代碼如下:
public class Test
{
public static void main(String[] args)
{
Human aPerson = new Human();
Class c1 = aPerson.getClass();
System.out.println(c1.getName());
Human anotherPerson = new Woman();
Class c2 = anotherPerson.getClass();
System.out.println(c2.getName());
}
}
class Human
{
/**
* accessor
*/
public int getHeight()
{
return this.height;
}
/**
* mutator
*/
public void growHeight(int h)
{
this.height = this.height + h;
}
private int height;
}
class Woman extends Human
{
/**
* new method
*/
public Human giveBirth()
{
System.out.println("Give birth");
return (new Human());
}
}
當我們呼叫物件的getClass()方法時,就得到對應Class物件的參考。
在c2中,即使我們將Women物件的引用向上轉換為Human物件的引用,物件所指向的Class類別物件依然是Woman。
Java中每個物件都有對應的Class類別對象,因此,我們隨時能透過Class物件知道某個物件「真正」所屬的類別。無論我們對引用進行怎樣的型別轉換,物件本身所對應的Class物件都是同一個。當我們透過某個引用呼叫方法時,Java總是能找到正確的Class類別中所定義的方法,並執行該Class類別中的程式碼。由於Class物件的存在,Java不會因為類型的向上轉換而迷失。這就是多態的原理。
getClass: 我是誰?
除了getClass()方法外,我們還有其他方式呼叫Class類別的物件。
複製代碼代碼如下:
public class Test
{
public static void main(String[] args)
{
Class c3 = Class.forName("Human");
System.out.println(c1.getName());
Class c4 = Woman.class
System.out.println(c2.getName());
}
}
上面顯示了兩種方式:
1.forName()方法接收一個字串作為參數,該字串是類別的名字。這將傳回對應的Class類物件。
2.Woman.class方法是直接呼叫類別的class成員。這將傳回對應的Class類物件。
Class類別的方法
Class物件記錄了對應類別的信息,例如類別的名字,類別所在的套件等等。我們可以呼叫對應的方法,例如:
複製代碼代碼如下:
getName() 傳回類別的名字
getPackage() 傳回類別所在的套件
可以利用Class物件的newInstance()方法來建立對應類別的對象,例如:
複製代碼代碼如下:
Human newPerson = c1.newInstance();
newInstance()呼叫預設的不含參數的建置方法。
我們可以獲得類別定義的成員:
複製代碼代碼如下:
getFields() 傳回所有的public資料成員
getMethods() 傳回所有的public方法
可以進一步使用Reflection分析類別。這裡不再深入。
Class類別更多的方法可查詢官方文件:
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html
Class類別的載入
當Java建立某個類別的對象,例如Human類別物件時,Java會檢查記憶體中是否有對應的Class物件。
如果記憶體中沒有對應的Class對象,那麼Java會在.class檔案中尋找Human類別的定義,並載入Human類別的Class物件。
在Class物件載入成功後,其他Human物件的建立和相關操作都會參考該Class物件。