2012-03-23 89 views
0

在:泛型與延伸

public class Organic<E> { 
    void react(E e) { 
    } 

    static void main(String[] args) { 
     Organic<? extends Elem> compound = new Organic<Elem>(); 
     compound.react(new Elem()); 
    } 
} 

class Elem {} 

爲什麼我得到下面的編譯錯誤?

方法react(capture#1-of ? extends Elem)在類型Organic<capture#1-of ? extends Elem>不適用於參數(Elem

+0

爲什麼你使用不同的參數爲變量聲明和對象實例?你想達到什麼目的? – biziclop 2012-03-23 11:35:59

+0

我不想實現任何目標。這只是一本書的練習。 – 2012-03-26 07:45:45

回答

1

http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

List是有界的通配符的示例。這個?代表着未知類型,就像我們之前看到的通配符一樣。然而,在這種情況下,我們知道這個未知類型實際上是Shape的一個子類型。 (注意:它可以是Shape本身,也可以是一些子類;它不需要從字面上擴展Shape。)我們說Shape是通配符的上界。

像往常一樣,使用通配符的靈活性需要付出代價。這個價格是現在寫入方法體內的形狀是非法的。例如,這是不允許的:

public void addRectangle(List<? extends Shape> shapes) { 
    // Compile-time error! 
    shapes.add(0, new Rectangle()); 
} 

你應該能夠找出爲什麼上面的代碼是不允許的。 shapes.add()的第二個參數的類型是?擴展Shape - Shape的未知子類型。由於我們不知道它是什麼類型,我們不知道它是否是Rectangle的超類型;它可能或可能不是這樣一個超類型,所以在那裏傳遞一個Rectangle是不安全的。

具體談論你的解決方案,你不能說與Elem類型的對象作出反應,與類型Organic<? extends Elem>你可以合法地分配compound = new Organic<ElemSubClass>() - 然後反應會導致編譯錯誤,你不能把它傳遞一個超類對象。

0

修改你的方法reactas每下面,它的工作:

void react(Elem e) { 

} 
0

的「?當你想允許用戶只傳遞SomeClass或它的子類作爲一個通用參數時,擴展SomeClass'用於定義泛型類型。這意味着你可以這樣做:

public class Organic<E extends Elem> { 
    void react(E e) { 
} 

,如果你想有機與ELEM的子類的參數進行調整。在主要的方法,你可以做這樣的事情:

Organic<Elem> compound = new Organic<ElemOrAnyElemSubclass>(); 

,因爲我知道沒有必要在方法體中使用

Organic<? extends Elem> 

整個代碼:

public class Organic<E extends Elem> { 
void react(E e) { 
} 

static void main(String[] args) { 
    Organic<Elem> compound = new Organic<Elem>(); 
    compound.react(new Elem()); 
    } 
} 
class Elem {} 
class ElemSubClass extends Elem {} // if you need 

而且你在表達的左側和右側部分使用相同的通用類型。這是非法的: Organic compound = new Organic();

不知道它是你想要的,但希望它會幫助