Java泛化要求隐式类型而不是通配符

时间:2015-09-17 11:19:23

标签: java generics

我上课了: public class WebDriverHighlighterListener extends AbstractWebDriverEventListener implements WebDriverEventListener { 代码enter image description here

当我使用带通配符的构造函数时,为什么它需要隐式类型?

1 个答案:

答案 0 :(得分:1)

有两个不同的问题。在Java 8之前,表达式Arrays.asList(X)总是具有类型List<TypeOfX>,您将其称为“隐式类型”。

此类型与您的通配符不兼容。

让我们用一个简单的例子来解释它。假设,我们声明了一个类型为

的变量
List<Class<String>> list=Arrays.asList(String.class);

这是一个列表,能够保存Class<String>类型的实例(只有一个,String.class)和没有别的

相反,类型列表

List<Class<? extends CharSequence>> list2;

允许我们完成所有这些:

list2.add(StringBuilder.class);
list2.add(String.class);
list2.add(CharBuffer.class);

因此,应该清楚的是,我们无法将list分配给list2,因为只有String.class因为它的元素才会突然被这些其他元素填充Class<? extends CharSequence>个对象。

如果你想拥有列表,保证你将从中检索的实例是Class<? extends CharSequence>类型,而不限制它的实际类型,即赋值与List<Class<String>>兼容,因为你不会去要将新元素存储到列表中,您可以使用

List<? extends Class<? extends CharSequence>> list3=list;// legal assignment

允许

Class<? extends CharSequence> cl=list3.get(0);

但尝试将新元素存储到list3将被编译器拒绝,因为实际的元素类型是未知的(好吧,除了存储null的尝试,因为它对所有引用都是合法的类型)。

或者你可以使用

List<Class<? extends CharSequence>> list4=Collections.unmodifiableList(list);

因为已知返回的列表将在运行时拒绝修改,所以在编译时接受这种类型转换。

当然,您也可以更改Array.asList表达式的类型。当你要修改列表时,这是正确的方法。

List<Class<? extends CharSequence>> list
    = Arrays.<Class<? extends CharSequence>>asList(String.class);

从Java 8开始,将使用目标类型自动推断此类型,因此以下是合法的Java 8代码:

List<Class<? extends CharSequence>> list=Arrays.asList(String.class);

Array.asList表达式是构造函数调用的参数时,这也有效。

这一切都适用于AbstractWebDriverEventListenerWebDriverEventListener,与适用于StringCharSequence的方式相同。