[英]Generics in Java, using wildcards
I have a question about Generics in Java, namely using wildcards. 我有一个关于Java中泛型的问题,即使用通配符。 I have an example class GenClass like this:
我有一个像这样的示例类GenClass:
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)". 它说“方法(setVar())不适用于参数(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 EI would have any class. 我认为我使用通配符的方式使得引用变量c的类型为GenClass,它将接受任何类作为参数 - 在EI的位置上将具有任何类。 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. 这意味着我创建了一个GenClass类型的对象,它具有一个类型为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.
所以,我认为现在GenClass中的E将是ExampleClass,我将能够使用方法setVar(),将其作为类型为ExampleClass的参数。 This was my assumption and understanding, but it seems that Java does not like it, and I am not right.
这是我的假设和理解,但似乎Java不喜欢它,我不对。 Any comment is appreciated, thank you.
任何评论表示赞赏,谢谢。
This exact situation is covered in the Java Generics Tutorial . Java Generics Tutorial中介绍了这种确切的情况。
Notice that [with the wildcard], we can still read elements from [the generic
Collection
] and give them typeObject
.请注意,[使用通配符],我们仍然可以从[泛型
Collection
]中读取元素并为它们指定类型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.由于我们不知道
c
的元素类型代表什么,我们无法向其添加对象。 Theadd()
method takes arguments of typeE
, the element type of the collection.add()
方法接受类型为E
参数,即集合的元素类型。 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.我们传递给
add
任何参数都必须是这种未知类型的子类型。 Since we don't know what type that is, we cannot pass anything in. The sole exception isnull
, which is a member of every type.因为我们不知道它是什么类型,所以我们无法传递任何内容。唯一的例外是
null
,它是每种类型的成员。
(emphasis mine) (强调我的)
mmyers has the correct answer, but I just wanted to comment on this part of your question (which sounds like your rationale for wanting to use the wildcard): mmyers有正确的答案,但我只想评论你的问题的这一部分(这听起来像你想要使用通配符的理由):
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 EI would have any class.
我认为我使用通配符的方式使得引用变量c的类型为GenClass,它将接受任何类作为参数 - 在EI的位置上将具有任何类。 This is just the declaration of the variable.
这只是变量的声明。 Then I initialize it with
然后我用它初始化它
If you really want to accomplish this, you could do something like without compilation errors: 如果你真的想要完成这个,你可以做一些没有编译错误的事情:
GenClass<Object> gc = new GenClass<Object>();
gc.setVar(new ExampleClass());
But then again, if you want to declare an instance of GenClass
that can contain any type, I'm not sure why you'd want to use generics at all - you could just use the raw class: 但话又说回来,如果你想声明一个可以包含任何类型的
GenClass
实例,我不确定你为什么要使用泛型 - 你可以只使用原始类:
GenClass raw = new GenClass();
raw.setVar(new ExampleClass());
raw.setVar("this runs ok");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.