2013-12-22 60 views
1

我遇到了原始類型轉換爲通配符參數化類型導致異常的問題。 原始類型非常不鼓勵,但替代品似乎也不想要。通配符類型不匹配與原始類型

考慮下面的類:

public static abstract class A<T> { 
    T t; 
    public abstract void add(T t2); 
} 
public static class C extends A<Double> { 
    @Override public void add(Double t2) { t += t2; } 
} 
public static class D extends A<String> { 
    @Override public void add(String t2) { t.concat(t2); } 
} 

以下代碼:

public static void main(String[] args) { 
    A<?>[] as = new A[2]; 
    as[0] = new C(); 
    as[1] = new D(); 
    for (A<?> a: as) 
     a.add(a.t);  // results in a type mismatch exception 
    for (A<?> a: as) 
     insideFor(a); // is not so neat 
    for (A a: as) 
     a.add(a.t);  // makes use of raw types 
} 
private static <T> void insideFor(A<T> a) { 
    a.add(a.t); 
} 

我該怎麼辦?

+0

它是什麼你試圖實現你的參數化類型?你所提供的選項幾乎都是你得到的。 –

+0

如果你使用'A ',你基本上是說「一個什麼都有」。你不能將一個對象傳遞給任何期望* nothing *的方法,因爲你不知道它的類型。 – Darkhogg

+3

是的,沒有辦法讓代碼安全,因爲[0]只能接受Double,而[1]只能接受String。沒有你可以指定的類型,因爲它可以讓你確定發生了什麼。這是因爲像'A <?擴展Object> [] as並不意味着每個'as [i]'都有一些類型'T'來擴展Object,使得[i]是一個A ;相反,這意味着有一些類型T擴展了Object,使得對於每個[i],因爲[i]是A 。這裏唯一的'T'是'Object'。 –

回答

1

第二種方法(「不是那麼整齊」)是這樣做的正規途徑。這被稱爲捕獲幫手。它利用捕獲來引入一個「局部」類型的變量。輔助方法通常是private,以便外部代碼不必知道它在那裏。

P.S. S不在任何地方使用

+0

感謝您的回覆。事實上,它應該是「私人的」,而「S」是我正在制定的更精細的例子的殘餘。 –

0

java泛型中有一些限制,通常可以通過良好的設計來避免。在這種情況下,我想補充「addInner()」方法,以A類:

public static abstract class A<T> { 
    T t; 
    public abstract void add(T t2); 
    public void addInner(){ 
     this.add(this.t); 
    } 
}