2009-02-02 76 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");