Java中的泛型,使用通配符 [英] Generics in Java, using wildcards

查看:110
本文介绍了Java中的泛型,使用通配符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Java中的泛型有一个疑问,即使用通配符。我有一个像这样的类GenClass的例子:

  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:ExampleClass @ addbf1
}

}

现在,如果我使用通配符并在测试类中写入:

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

地点:$ b​​
$ b

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

编译器对这个新语句没有任何问题,但它抱怨

  c.setVar(ec); 

它表示该方法(setVar())不适用于参数(ExampleClass) 。为什么我会收到此消息?



我认为我使用通配符的方式使参考变量c为GenClass类型,它将接受任何类的参数 - 在EI的地方会有任何班级。这只是变量的声明。然后我用

  new GenClass< ExampleClass>()
这是我的假设和理解,但似乎Java并不喜欢它,而我却说得不对。
任何意见,谢谢。

解决方案

确切的情况在 Java泛型教程



< blockquote>

请注意[使用通配符],我们仍然可以从[通用集合]中读取元素,并为它们键入对象。这总是安全的,因为无论实际的集合类型如何,它都包含对象。然而,向它添加任意对象并不安全:



 集合<?> c = new ArrayList< String>(); 
c.add(new Object()); //编译时错误




由于我们不知道元素是什么类型 c 代表,我们不能添加对象。 add()方法使用 E 类型的参数,这是集合的元素类型。当实际的类型参数是时,它代表某种未知的类型。 我们传递给 add 的任何参数必须是这个未知类型的子类型。因为我们不知道是什么类型,所以我们不能传入任何东西。唯一的例外是 null ,它是每种类型的成员。


(强调我的)


I have a question about Generics in Java, namely using wildcards. I have an example class GenClass like this:

public class GenClass<E> {

    private E var;

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

    public E getVar() {
        return var;
    }
}

I have another simple class:

public class ExampleClass {

}

I have written the following test class:

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: ExampleClass@addbf1
    }

}

Now, if I use a wildcard and write in the test class this:

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

on the place of:

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

the compiler has no problem with this new statement, however, it complains about

c.setVar(ec);

It says that "the method (setVar()) is not applicable for the arguments (ExampleClass)". Why do I get this message?

I thought that the way I have used the wildcard, makes the reference variable c be of type GenClass, which would accept as parameter any class - on the place of E I would have any class. This is just the declaration of the variable. Then I initialize it with

new GenClass<ExampleClass>()

which means that I create an object of type GenClass, which has as parameter a class of type ExampleClass. So, I think that now E in GenClass will be ExampleClass, and I would be able to use the method setVar(), giving it as argument something of type ExampleClass. This was my assumption and understanding, but it seems that Java does not like it, and I am not right. Any comment is appreciated, thank you.

解决方案

This exact situation is covered in the Java Generics Tutorial.

Notice that [with the wildcard], we can still read elements from [the generic Collection] and give them type Object. This is always safe, since whatever the actual type of the collection, it does contain objects. It isn't safe to add arbitrary objects to it however:

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

Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type.

(emphasis mine)

这篇关于Java中的泛型,使用通配符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆