2009-09-30 80 views
17

我有一個保證僅包含一個類型對象的列表。這是由庫中的一些底層代碼創建的,我無法更新。我想根據傳入的List對象創建一個List <ObjectType>,以便我的調用代碼正在與List <ObjectType>對話。在Java 1.5中將非泛型列表類型轉換爲泛型列表類型

什麼是將列表(或任何其他對象集合)轉換爲列表的最佳方式<ObjectType>。

回答

13

當不指定泛型類型的類型參數,使用通配符遺留代碼操作間。例如,假設您正在調用僅返回一箇舊庫的方法的原料Collection

Collection getItems(); 

在你的代碼,結果分配給一個通配符聲明的變量:

Collection<?> items = widget.getItems(); 

這方式,你保持類型安全,所以你不會得到任何警告。

遺留代碼可能會指定(在最有可能的評論中)通用參數應該是什麼。例如:

/** 
* @return the items, as a Collection of {@link Item} instances. 
*/ 
Collection getItems(); 

在這種情況下,您可以選擇。你可以把結果轉換爲Collection<Item>,但是如果你這樣做,你就可以100%地依賴第三方庫,並放棄對Java通用類型的保證:在運行時產生的任何ClassCastException都會直接發生投。

如果您不完全信任第三方庫,但仍需要生成Collection<Item>?然後創建一個新的集合,並在將它們轉換爲預期類型之後添加內容。這樣,如果庫中存在一個錯誤,你馬上就會發現它,而不是讓代碼很遠,後來神祕地用ClassCastException炸燬了它。

例如:

Collection<?> tmp = widget.getItems(); 
Collection<Item> items = new ArrayList<Item>(tmp.size()); 
for (Object o : tmp) 
    items.add((Item) o); /* Any type error will be discovered here! */ 

對於其中類型參數不是在編譯時已知的情況下,則可以使用Collections類的type-checked collection factories

+0

問題是,除了沉默「原始類型」警告之外,這並沒有真正爲您帶來任何收益。轉換爲泛型意味着要利用它的好處! – 2009-09-30 15:58:42

+1

泛型的好處是什麼?這不是讓你的代碼看起來很漂亮,而且需要更少的輸入!它是這樣的:*如果編譯沒有警告,你的代碼保證是類型安全的。*就是這樣。當你忽略或禁止這些警告時,你可能根本不會使用泛型,因爲你所做的就是創建一些情況,其中沒有cast操作符的代碼會神祕地引發'ClassCastException'。 – erickson 2009-09-30 16:07:02

11

您可以簡單地把列表:

List raw = new ArrayList(); 
    List<String> generic = (List<String>) raw; 
+2

如果列表確實能夠保存一種類型的項目,這是一個很好的答案。 – 2009-09-30 15:55:02

+1

這是一個很大的「如果」。這很大程度上取決於上下文。 – erickson 2009-09-30 16:11:54

+0

我可以保證列表將保存一種類型的項目。這是用Java 1.4前泛型編寫的代碼。 – 2009-09-30 17:35:53

1

最好,最安全的方法是使用java.util.Collections中的方法「checkedList(名單列表,類型)」

通過這種方法,所有在舊列表中的項目將早檢查可能。

+0

Java 5中的'checkedList'不僅適用於新的(和空的)通用列表嗎?您是否建議我們在Java 5之前使用非泛型'checkedList'?這種傳統形式不會轉換爲通用列表。 – 2010-08-20 19:12:44

0

如果你只是在任何舊地方投了List<T>,你將得到一個「未檢查」的編譯器警告。我們通過將其轉移到實用方法來解決這個問題。

public class Lists { 
    @SuppressWarnings({"unchecked"}) 
    public static <T> List<T> cast(List<?> list) { 
     return (List<T>) list; 
    } 
} 

呼叫者現在不會收到警告,例如,:

for (Element child : Lists.<Element>cast(parent.getChildren())) { 
    // ... 
} 

checkedList效用在理論上是一個偉大的想法,但在實踐中它吮吸對你有期望類的通過。我希望Java最終能獲得運行時的通用輸入信息。

1

試試這個:

List<ObjectType> objectsWithType = Arrays.asList((ObjectType[])wildcardObjects).toArray()); 

但請記住,這將產生一個固定長度的列表。如果您嘗試添加或刪除此列表中的元素,它將引發錯誤。所以在使用Arrays.asList()時務必小心。