2014-09-20 65 views
1

以下示例取自Generics FAQ通配符參數化不接受對象 - 爲什麼?

public class Box<T> { 
    private T t; 

    public Box(T t) { 
     this.t = t; 
    } 

    public void put(T t) { 
     this.t = t; 
    } 

    public T take() { 
     return t; 
    } 

    public static void main(String[] args) { 
     Box<?> box = new Box<Object>(new Object()); 
     Object o = new Object(); 
     box.put(o); // Compiler error 
     o = box.take(); // ok 
    } 

} 

如果你看看反編譯後的版本put()是否接受Object。那麼爲什麼編譯器不接受put()中的Object呢?

public class Box 
{ 

    public Box(Object t) 
    { 
     this.t = t; 
    } 

    public void put(Object t) 
    { 
     this.t = t; 
    } 

    public Object take() 
    { 
     return t; 
    } 

    public static void main(String args[]) 
    { 
     Box box = new Box(new Object()); 
     Object o = new Object(); 
     o = box.take(); 
    } 

    private Object t; 
} 

回答

2

編譯器的類型檢查,Box<?>Box<Object>不同。一個Box<Object>肯定會包含一個對象,所以可以撥打put(Object)。 A Box<?>有一個未知的類型參數。未知與Object不同。例如,可以是Integer。在Box<Integer>上調用put(Object)將是一個錯誤。如果編譯器接受它,那麼你可以修改你的程序:

Box<?> box = new Box<Integer>(1); 
Object o = new Object(); 
box.put(o); 

並且有一個非常明確的類型不匹配。允許編譯最後一行只是將錯誤推遲到運行時。

換句話說,泛型類型擦除並不意味着編譯器在編譯時不知道泛型類型。在信息被刪除之前儘量發現錯誤。

相關問題