我上课了:
public class WebDriverHighlighterListener extends AbstractWebDriverEventListener implements WebDriverEventListener {
代码
当我使用带通配符的构造函数时,为什么它需要隐式类型?
答案 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
表达式是构造函数调用的参数时,这也有效。
这一切都适用于AbstractWebDriverEventListener
和WebDriverEventListener
,与适用于String
和CharSequence
的方式相同。