簡體   English   中英

課堂上未經檢查的警告<Collection>

[英]unchecked warning on Class<Collection>

假設我具有以下方法,該方法可用於創建指定的給定類型的集合。

private static Collection<?> void create(Class<? extends Collection<?>> cls) {
    return cls.newInstance();
}

如果在運行時傳遞cls參數,那么這一切都很好:

List<String> list = new LinkedList<String>();
create(list.getClass());

但是,如何在沒有未經檢查的警告的情況下在代碼中調用此方法? 假設我想執行以下操作:

create(LinkedList.class);

它將抱怨未定義create(Class),嚴格來說,這是正確的,因為List不是#capture的Collection,但是我如何使它工作?

非常感謝!

尼爾·古夫特(Neal Gafter) 在這里幾乎完全討論了這個問題。 解決方法是使用超級類型令牌 我相信,Guice就是用來維護通用類型信息的。

基本上,這是一個額外的類,可以用來表示一個類型,而不是使用Foo.class 您可以這樣使用它:

TypeReference<LinkedList<String>> x = new TypeReference<LinkedList<String>>() {};
create(x);

請注意,您嘗試使用原始類型LinkedList仍然會導致編譯器抱怨,這是故意的-使用原始類型時,您基本上選擇了類型安全。 但是,此方案允許您以其他方式難以表達的泛型類型。

我們這里有兩種通用類型,一種是集合的子類型,一種是集合的元素類型。 以下代碼可以工作:

private static <C extends Collection<E>, E>
C create(Class<C> cls) throws Exception
{
    return cls.newInstance();
}

使用示例。 沒有警告。

    Class<LinkedList<String>> clazz = ...;
    LinkedList<String> result = create(clazz);

現在的問題變成我們如何獲得clazz 您必須非常說服編譯器:

    List<String> list = new LinkedList<String>();
    clazz = (Class<LinkedList<String>>)list.getClass();

    clazz = (Class<LinkedList<String>>)(Class<?>)LinkedList.class;

我們可以使用一種實用方法來簡化類型轉換:

public static <C extends Collection, E, T extends Collection<E>>
Class<T> type(Class<C> classC, Class<E> classE)
{
    return (Class<T>)classC;
}

//usage:
    clazz = type(LinkedList.class, String.class);
    result = create(clazz);

有趣的是遞歸的:

    Class<LinkedList<LinkedList<String>>> clazz2;
    LinkedList<LinkedList<String>> result2;

    clazz2 = type(LinkedList.class, clazz);
    result2 = create(clazz2);

但是在某個時候,我們必須停止這場愚蠢的比賽。 泛型打字應該幫助我們,而不是折磨我們。 當它變得太麻煩並且使我們的程序無法閱讀時,請將其刪除。 使用我們幸福生活多年的該死的原始類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM