2012-04-13 186 views
5

我有一個方法需要List<?>作爲參數。Java泛型類型參數

public static String method(List<?> arg){ 
    // Do something based on type of the list 
} 

//I call the method as below 
List<ClassA> listA = new ArrayList<ClassA>(); 
List<ClassB> listB = new ArrayList<ClassB>(); 
method(listA); 
method(listB); 

method,我怎麼知道,如果argClassA一個ListClassB一個List

+2

聲明參數類型爲''意思是說你對實際類型不感興趣。 – biziclop 2012-04-13 22:33:35

+0

重複這個http://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list – evanwong 2012-04-13 22:34:55

+0

@evanwong - 不知道我是否會同意它的愚蠢。 – djangofan 2012-04-13 22:37:32

回答

3

從用戶的回答稱爲Romain「如果您使用<?>,則表示您不打算在任何地方使用參數化類型。要麼轉到特定類型(對於您的情況,似乎列表< String> )或非常通用的列表對象>「

另外,我相信如果您使用問號,編譯器將不會捕獲類型不匹配,直到運行時(有效Java的實體化; p.119),繞過擦除,並且有效減少使用泛型類型所帶來的好處?

回答提問者的問題:如果使用列表< Object>然後嘗試將其轉換爲A或B,可能使用instanceOf,這可能是一種告訴它是什麼的方法。我敢打賭,儘管如此,還是有更好的方法去做。

+1

對於OP,+1正有效地消除了使用泛型類型獲得的好處_ – jahroy 2012-04-13 23:11:36

+1

意味着「我沒有使用泛型,但我想擺脫編譯器警告。」 – user949300 2013-02-07 23:31:23

+3

-1,因爲這個答案鼓勵錯誤的編碼習慣。定義一個採用泛型類型參數的方法是這樣做的適當方式 - 它爲您提供了類型安全性,並且不需要混亂的轉換。請參閱jahroy的回答。 – 2013-03-19 03:19:38

1

鑑於您的示例,無法知道List的泛型類型參數是什麼。它們在實例級別被刪除。

14

從技術上講,你CAN使用instanceof檢查對象是否是某種類型。

然而,這是不是一個好主意。

你聲明你的方法的方式,它可以接受任何類型的列表,所以它並不一定會是A或B.

很難告訴你要怎麼做,但你可能應該讓你的方法是通用的。

你可以這樣做是這樣的:

public static <T> String method(List<T> arg) { 
    // We now know that the type of the list is T, which is 
    // determined based on the type of list passed to this 
    // method. This would demonstrate the point better if 
    // the return type was T, but I'm leaving the return type 
    // as String, because that's what your code returns. 
} 

這裏有一個更好的例子

如果你想創建一個返回列表的第一個元素的一般方法,你會這樣做:

public static <T> T firstElement(List<T> theList) { 
    if (theList == null) { 
     return null; 
    } 
    T objectOfTypeT = theList.get(0); 
    return objectOfTypeT; 
} 

請注意,返回現在類型爲T

因爲我們使這個方法是通用的,它可以返回列表中使用的相同類型。

您通常只會返回theList.get(0),但我添加了一行以使泛型的用途更加明顯。

語法的說明:

  • <T>表明,該方法採用一個名爲T

  • 緊隨T是返回類型一個類型參數(就像你通常會返回字符串,整數等)。

  • List參數中的T是編譯器知道什麼是T

這允許編譯器說:「這種方法需要類型T的東西哦,看...這樣的例子也是T類型如果有人通過字符串列表這種方法,且T必須是一個字符串。如果有人通過整數這種方法的列表,T必須是整數。

相反,你的方法可以返回一個字符串,它根本不知道是什麼類型的使用列表。


也...

如果A和B都延長了同一個班級,一個名爲TheParentClass,你可以聲明你的方法是這樣的:

public static String method(List<? extends TheParentClass> arg) 

這樣一來,你就知道多一點關於你的參數的可能類型(並且可以從編譯時類型檢查中受益)。

+0

最後一個例子你給出了「擴展TheParentClass」大概是怎麼樣的?是「意思」被使用。允許使用?沒有延伸位,就像大衛梅森所說的那樣,糟糕的做法卻是合法的。我認爲jahroy應該被授予這個問題的答案,而不是我,因爲他釘了它。 – djangofan 2013-03-19 20:10:32