2014-05-24 26 views
1

爲內部使用製作一個API,我需要一些Java抽象,我不知道該怎麼做。鑄造派生Java接口(泛型)的集合

  • 有一個接口A與派生接口。
  • 假設A的其中一個擴展接口被稱爲B
  • 假設有一個類C實施B

我有一個工廠/池類˚F從中我想實例(或一組或類似的集合)的列表。 我想基本上是這樣的:

List<B> instances = F.getAllSuitableInstances(parameters); 

給我通過我的參數指定爲B的集合

第一次嘗試使用此函數簽名

public List<A> getAllSuitableInstances(parameters);

的所有實例

但是當我嘗試將結果列表轉換爲列表以供使用時,我會告知 「不兼容的類型」 - 即使B是派生的從A

d所以我試了一下Java庫做:

public <T> List<T> getAllSuitableInstances(parameters, T);

,並嘗試調用以b作爲第二個參數。但這也不起作用 ,因爲T由於某種原因必須作爲實例提供,並且接口不能有實例。

我知道我可以使用<?>進行鑄造,但我希望將它作爲類型安全。

那麼,完成這件事的最好方法是什麼?

+0

你是對的工作 - 回答上面的回答我的引用以及問題。但我沒有找到其他問題,因爲我沒有找到它的關鍵字(狗,動物,多態)。也許其他人會更像我這樣做他們的搜索,所以這個問題的存在可能仍然有用。 – foo

回答

1

即使B從A派生

你必須要小心在這裏 - Java的泛型是不變的,這意味着Something<Superclass>Something<Subclass>超類(如List<Number>超級List<Integer>)。關於這一點,有很多關於SO的問題,所以我不會重複其他人可以更有效地解釋的信息,例如herehere

至於你的第二個簽名,在我看來,T(parameters, T)是不必要的。

public <T> List<T> getAllSuitableInstance(parameters); 

應該工作,除非我誤解了你的要求。這樣做的缺點是,T可能是任何東西,所以你可以在T類型的對象上調用的方法有所限制,但是如果你不這樣做,那麼不需要擔心。

如果您的接口中的方法對於使您的方法正常工作(似乎不是這樣,但以防萬一),您可以隨時添加邊界(例如public <T extends A> List<T>...)到您的泛型類型,因此編譯器知道您的方法中的所有T實例均爲AA的子類型。

如果您需要使用類型的T在你的方法(假設爲instanceof檢查),一種選擇是傳遞一個Class對象,並使用它的方法來執行運行時等價的instanceof檢查和鑄造(其他中選項):

public <T> List<T> getAllSuitableInstance(parameters, Class<? extends T> clazz); // Might be able to use just Class<T> too 

希望有幫助。如果我對你需要的東西有錯誤,請告訴我。

+0

就是這樣,謝謝 - 版本號爲的版本爲我提供了一些類型安全性,同時還提供了所需的靈活性。你的鏈接爲這個答案增加了價值,使它對其他讀者更有用,所以我更喜歡(並接受)這個答案。 – foo

+0

@foo沒問題!只是一個(可能是多餘的)音符 - 「」的版本主要用於*方法中的工作*。如果你只使用普通的'T',我相信編譯器能夠找出'T - > B',但是在這個方法中做你的工作可能會有點棘手,因爲你完全不知道' T'是(除非它是你的一個參數的一部分,就像'Class'參數的版本一樣)。 – awksp

1

這是一個普遍的誤解,當談到與泛型編程,但它是學習

,當我們有兩個具體類型AB(例如,NumberInteger)的一個重要概念,MyClass<A>沒有與MyClass<B>的關係,不管AB是否有關係。

MyClass<A> and MyClass<B> is Object的共同父項。

甚至不需要傳遞類,你在第二個選項

提到這應該爲你

public <T> List<T> getAllSuitableInstances(parameters) { 
List<T> list = new ArrayList<>(); 
//content add to list 
    return list; 
}