Java是一種強型別語言,每個執行個體都必須有指定的類型。實際上,Java類型有兩種宣告類型和 運行時類型 (也可以相應的說是靜態類型 和動態類型 ). 像Python這樣的弱類型語言通常稱為無類型,但是這樣說並不嚴謹,因為每個執行個體都有它的運行時類型。你只是不用事先聲明一個執行個體的類型而已。
要想調用一個對象中的方法,這個方法需要在宣告類型中存在。也就是說,你只能調用定義在父類中的方法,即使該執行個體是一個確定的子類型:
List list = new ArrayList();
list.add("data"); // 在這裡沒問題
list.ensureCapacity(4); // 這裡就不行了ensureCapacity() 只在ArrayList中才有。
如果我們要調用實際類型中的方法,我們首先要將它轉為正確的類型。在本例中,我們可以把 ArrayList 轉為List,因為ArrayList實現了List 介面. 也可以在運行時動態檢驗,使用 list instanceof ArrayList.
可擴充的介面
糟糕的是,一個類不能總是實現你所需要實現的介面。可能是因為這隻對少數幾種情況才有效,或者它是一個沒有被關聯的庫中的類型,或者這個介面在後期又被改變了。
這種情況就可以使用IAdaptable。 你可以把 IAdaptable 動態進行類型轉化。使用如下方法避免直接的類型轉化:
Object o = new ArrayList();
List list = (List)o;
我們可以這樣做:
IAdaptable adaptable = new ArrayList();
List list = (List)adaptable.getAdapter(java.util.List.class);
你可認為它是一種類型動態轉化; 我們把adaptable轉為List執行個體。
為什麼不直接轉化,而要用額外的getAdapter() 呢?這種機制可以使我們將目標類轉化為沒有實現的介面。例如, 我們可能想使用HashMap 作為一個 List, 儘管他們並不相容。
IAdaptable adaptable = new HashMap();
List list = (List)adaptable.getAdapter(java.util.List.class);
實現IAdaptable
大多數IAdaptable的實現看起來就想是為支援類型構造多個if運算式的疊加。如果要為HashMap實現getAdapter() 可以這樣:
public class HashMap implements IAdaptable {
public Object getAdapter(Class clazz) {
if (clazz == java.util.List.class) {
List list = new ArrayList(this.size());
list.addAll(this.values());
return list;
}
return null;
}
// ...
}
返回的是一個對自身的代理,而不是直接轉化類型。如果請求的是不支援的類型,可以直接返回null表明失敗,這樣比拋出異常要好。