Qua*_*nic 5 java generics collections
这是jdk1.7.0_04.
我试图使用Collections.emptyList()而不是new在条件中使用我自己的空列表:
List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.emptyList();
Run Code Online (Sandbox Code Playgroud)
但是得到以下错误:
error: incompatible types
List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.emptyList();
^
required: List<String>
found: List<CAP#1>
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ? extends Object
1 error
Run Code Online (Sandbox Code Playgroud)
我能够想到我需要改变一些事情:
List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.<String>emptyList();
Run Code Online (Sandbox Code Playgroud)
但作为解决这个问题的一部分,我遇到了奇怪的(对我来说,无论如何)情况:
List<String> alwaysEmpty = Collections.emptyList();
Run Code Online (Sandbox Code Playgroud)
编译好,但是:
List<String> alwaysEmpty = (List<String>) Collections.emptyList();
Run Code Online (Sandbox Code Playgroud)
给出以下编译错误:
error: inconvertible types
List<String> alwaysEmpty = (List<String>) Collections.emptyList();
^
required: List<String>
found: List<Object>
Run Code Online (Sandbox Code Playgroud)
有没有搞错??
现在我可以理解,或许由于一些奇怪的原因,使用条件运算符会以某种方式阻止类型推断系统意识到emptyList()调用的类型参数应该是String,因此需要明确指定.但是为什么插入一个(公认的多余的)演员把事搞乱了?
但是为什么插入一个(公认的多余的)演员把事搞乱了?
因为现在表达式Collections.emptyList()本身不是任何赋值的目标 - 所以应该选择什么类型的参数?最好只指定type参数:
// Redundant here, but just as an example
List<String> alwaysEmpty = Collections.<String>emptyList();
Run Code Online (Sandbox Code Playgroud)
它也适用于条件运算符:
public static void main(String[] args) {
List<String> list = (args != null)
? Arrays.asList(args) : Collections.<String>emptyList();
}
Run Code Online (Sandbox Code Playgroud)
我将接受Jon的回答,但也希望列出一些人刚刚在SO之外传递给我的答案.它是提交给Sun/Oracle的关于此事的错误报告的链接.评估错误的人对正在发生的事情有一个有用的解释.摘录:
这里的提交者似乎假设条件表达式的类型是分配的LHS上的类型(
List<String>在这种情况下).事实并非如此:正如JLS所述,条件表达式的类型:"条件表达式的类型是将捕获转换(第5.1.10节)应用于
lub(T1, T2)(§15.12.2.7)的结果."重要的是要理解为什么有必要应用lub.请考虑以下示例:
class A {}
class B extends A{}
class C extends A{}
class Foo<X>
Foo<? extends A> l = b ? new Foo<B>() : new Foo<C>()
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们认为LHS属于类型,
Foo<? extends A>而RHS属于类型lub(Foo<B>, Foo<C>),即Foo<? extends B&C>.