2009-02-02 119 views
4

我對Java中的泛型有一個疑問,即使用通配符。我有一個例子類GenClass這樣的:Java中的泛型使用通配符

public class GenClass<E> { 

    private E var; 

    public void setVar(E x) { 
     var = x; 
    } 

    public E getVar() { 
     return var; 
    } 
} 

我還有一個簡單的類:

public class ExampleClass { 

} 

我寫了下面的測試類:現在

public class TestGenClass { 

    public static void main(String[] str) { 

     ExampleClass ec = new ExampleClass(); 

     GenClass<ExampleClass> c = new GenClass<ExampleClass>(); 

     c.setVar(ec); 
     System.out.println(c.getVar()); // OUTPUT: [email protected] 
    } 

} 

,如果我用一個通配符並寫在測試類中:

GenClass<?> c = new GenClass<ExampleClass>(); 

上的地方:

GenClass<ExampleClass> c = new GenClass<ExampleClass>(); 

編譯器有這個新的說法沒有問題,但是,它抱怨

c.setVar(ec); 

它說,「方法(SETVAR())不適用爲參數(ExampleClass)「。爲什麼我會收到此消息?

我認爲我使用通配符的方式使得引用變量c是GenClass類型,它將接受任何類作爲參數 - 在E的地方我將擁有任何類。這只是變量的聲明。然後,我

new GenClass<ExampleClass>() 

初始化它這意味着我創建類型GenClass,其具有作爲參數的一類ExampleClass類型的一個對象。所以,我認爲現在GenClass中的E將是ExampleClass,我將能夠使用方法setVar(),並將它作爲ExampleClass類型的參數。 這是我的假設和理解,但似乎Java並不喜歡它,而我卻說得不對。 任何意見表示讚賞,謝謝。

+1

根據您的用戶歷史記錄,您從未接受過答案。你認爲你現在可以開始嗎?你甚至可以得到2個代表點和一個免費的徽章(第一次)。 :d – 2009-02-05 16:29:01

回答

14

確切的情況在Java Generics Tutorial中涵蓋。

注意[用通配符],我們仍然可以讀取[通用Collection]元素,並給他們鍵入Object。這總是安全的,因爲無論實際的集合類型如何,它都包含對象。它是不安全的任意對象添加到它不過:

Collection<?> c = new ArrayList<String>(); 
c.add(new Object()); // Compile time error 

因爲我們不知道是什麼的c代表元素類型,我們不能將對象添加到它。 add()方法採用類型爲E的參數,該集合的元素類型。當實際類型參數是?時,它代表某種未知類型。 我們傳遞給add的任何參數必須是此未知類型的子類型。由於我們不知道是什麼類型,我們不能通過任何東西。唯一的例外是null,它是每種類型的成員。

(重點煤礦)

2

mmyers有正確的答案,但我只是想在你的問題(這聽起來像你的理由爲希望使用通配符),這部分評論:

我認爲我使用通配符的方式使得引用變量c是類型GenClass,它將接受任何類的參數 - 在EI的位置上將具有任何類。這只是變量的聲明。然後,我

初始化它如果你真的想做到這一點,你可以不喜歡沒有編譯錯誤:

GenClass<Object> gc = new GenClass<Object>(); 
gc.setVar(new ExampleClass()); 

但話又說回來,如果你想聲明的GenClass一個實例,可以包含任何類型,我不確定爲什麼要使用泛型 - 您可以使用原始類:

GenClass raw = new GenClass(); 
raw.setVar(new ExampleClass()); 
raw.setVar("this runs ok");