運行時類型信息使得你可以在程序運行時發現和使用類型信息。主要有方式:一種是“傳統的”RTTI;一種是“反射”機制,它允許在程序運行時發現和使用類的信息。
面向對象編程的目的是:讓代碼只操作對基類的引用,這就是多態。
RTTI的含義是:在程序運行時,識別一個對象的類型。
abstract class Shape {
private static final TAG = Shape.class.getSimpleName();
public String getTAGName() {
return TAG;
}
void draw();
}
class Circle extends Shape {
private static final TAG = Circle.class.getSimpleName();
public String getTAGName() {
return TAG;
}
public void draw() {
System.out.println(getTAGName());
}
}
class Square extends Shape {
private static final TAG = Square.class.getSimleName();
public String getTAGName() {
return TAG;
}
public void draw() {
System.out.println(getTAGName());
}
}
public class Shapes() {
public static void main(String[] args) {
List<Shape> shapeList = Array.asList(new Circle(),new Square(),new Circle());
for(Shape shape:shapeList) {
shape.draw();
}
}
}
在從數組中取出元素時,實際上這種容器把所有的事物當做Object,並會將自動轉化爲Shape。
Class對象:
包含 了與類有關的信息。我認爲static的成員變量就是儲存在此對象中的,最終已.class文件形式存儲。事實上,Class對象就是用來創建類的所有“常規”對象的。每一個class都有一個Class對象。所有類都是在對其第一次使用時,動態加載到JVM中的。另外,類的構造函數其實就是static成員。因此,java程序在運行之前並非完全已經加載的。如果尚未加載,默認的類加載器就會根據類名查找.class文件。一但一個類的Class對象被載入內存,它就用來創建這個類的所有對象。
Class.forName(“name”)是Class類的一個static成員方法,返回Class對象。如果你已經擁有了一個類的對象,你可以調用Object的方getClass()得到該類的Class對象。也可以使用類名.class得到Class對象。另外,Class的newInstance()方法是“虛擬構造器”的一種途徑,但是構造的類必須具有默認構造器,而且得到的引用是Object類型的,指向的是實際的類類型。
使用類字面常量,不僅簡單而且更加安全。它在編譯時進行類型檢查(因此不需要置於try語句中)。另外,對於基本數據類型的包裝器類都有一個標準字段TYPE,TYPE字段是一個引用,指向基本數據類型的Class對象。
注意,使用“.class”創建Class對象的引用時,不會自動初始化該Class對象。實現了惰性。在使用泛化的Class對象時:
Number類的對象的Class對象不能 賦值爲Integer對象的Class對象,因爲兩者的Class對象並不是 父類子類的關係,雖然Integer是 繼承自Number的。
Class<Number> generic = int.class;\\是錯誤的
爲了 解決此問題引入通配符。在Java中Class
Class<? extends Number> bounder = int.class;
bounder = double.class;
bounder = Number.class;
向Class引用中添加泛型語法的目的是爲了提供編譯時的類型檢查。當你使用泛型語法作用於於Class對象時,newInstance()將返回該對象的確切類型,而且不是Object類型。
類型轉換前先做類型檢查:instanceof