[英]My generics test in Java doesn't work!
我正在做一些Java學習,特別是在泛型領域。
我對C#中的泛型非常熟悉,但在Java中,這是一個完全不同的故事。
我使用了一些適合測試的樣本,我能夠用Java復制我的大部分C#代碼。
但是,當我嘗試以下示例時,它不起作用:
private static <T> void swapKundeData(ArrayList<T> data, int index1, int index2) {
T temporary = (T) data.get(index1);
data.set(index1, data.get(index2)); //Does not compile
data.set(index2, temporary); //Does not compile
}
我收到的錯誤是:
在ArrayList類型中的方法set(int,capture#5-of?extends ExtendTest)不適用於參數(int,ExtendTest)
相當於這個在C#中運行得很好 - 所以發生了什么?
我已經讀到Java在泛型方面受到了很多批評。 這是批評的一部分嗎? 數據變量的Remove和Add方法工作得很好。
好吧,我會用
List<Kunde>
代替
ArrayList<?>
因為你無論如何都要去昆德:)。
它不起作用的原因是您不知道傳遞的對象的類型。 因此,如果您設置一個可能是錯誤類型的Kunde(因為使用ArrayList <?>,您可以傳遞ArrayList <String>並在其上設置Kunde將是錯誤的類型)。
另一種可能性是:
private static <T> void swapData(List<T> data, int index1, int index2) {
T temporary = data.get(index1);
data.set(index1, data.get(index2)); //Does compile
data.set(index2, temporary); //Does compile
}
要完成我的咆哮,只需使用Collections的swap方法。
如果你知道你的ArrayList
包含Kunde
對象,那么你應該聲明方法參數ArrayList<Kunde>
; 沒有必要使用通配符。 正如您所看到的,它會導致編譯時類型錯誤。
有關該問題的完整說明,請參閱http://download.oracle.com/javase/tutorial/extra/generics/wildcards.html 。
你的問題的原因是你聲明了一種ArrayList<?>
,這意味着“一個列表應該只包含某種類型,但我不知道哪一種”。 這樣做的結果是,你從列表中取出的對象唯一知道的是它們是Object
類型,因為一切都是(除了原語,它不能在集合中)。 但更重要的是,您不能將任何內容放入列表中,因為您不知道它受約束的類型。
這就是為什么使用?
通配符很少適合。 在幾乎所有情況下,您應該使用具體類型或命名有界類型:
private static void swapKundeData(List<Kunde> data, int index1, int index2) {
Kunde temporary = data.get(index1);
data.set(index1, data.get(index2));
data.set(index2, temporary);
}
請注意List
接口的使用,這使得代碼可以更靈活地接受它所接受的內容。
private static <T> void swap(List<T> data, int index1, int index2) {
T temporary = data.get(index1);
data.set(index1, data.get(index2));
data.set(index2, temporary);
}
這是真正通用的解決方案,它是類型安全的,但不需要知道列表元素的類型。 你實際上並沒有通過使用Generics獲得任何類型的安全性( Object
也可以這樣做),但你可以返回一個交換元素,編譯器會知道返回值與列表元素的類型相同。
問題是Eclipse。
我沒有保存文件,所以顯然沒有重新編譯。
哇,我對IDE的無能力和煩惱感到非常滿意,比如速度。
那好吧。
我注意到這個問題已被編輯,以前的答案沒有多大意義。
從查看問題編輯,值得注意的是,如果您希望客戶端看到如下方法:
public static void swapKundeData(List<?> data, int index1, int index2) {
但是你想要實現:
public static <T> void swapKundeData(List<T> data, int index1, int index2) {
可以捕獲通配符,並且具有客戶端友好表單的方法可以轉發為實現友好的形式:
public static void swapKundeData(List<?> data, int index1, int index2) {
swapKundeDataImpl(data, index1, index2)
}
private static <T> void swapKundeDataImpl(List<T> data, int index1, int index2) {
(我在這里假設“kunde”不是一個粗魯的詞。)
總結Oli所說的內容,你不能分配給“未知類型”的集合嗎? 因為java不知道應該去那里。 但是,由於每個“未知類型”仍然是一個對象,因此它們可以安全地調用“getter”方法,因為它們將始終返回Object類型的對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.