Collections.emptyList()和/或Java通用方法的奇怪类型推断行为?
这是jdk1.7.0_04
。Collections.emptyList()和/或Java通用方法的奇怪类型推断行为?
我尝试使用Collections.emptyList()
,而不是new
荷兰国际集团我自己的空单在条件:
List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.emptyList();
但出现以下错误:
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
我能身影,我需要改变的东西:
List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.<String>emptyList();
但作为工作的一部分关于这一点,我遇到了奇怪的(对我来说,反正)局面:
List<String> alwaysEmpty = Collections.emptyList();
编译罚款,但:
List<String> alwaysEmpty = (List<String>) Collections.emptyList();
提供了以下编译错误:
error: inconvertible types
List<String> alwaysEmpty = (List<String>) Collections.emptyList();
^
required: List<String>
found: List<Object>
什么鬼??现在
我可以理解,也许一些奇怪的原因使用条件运算符是从某种程度上意识到了emptyList()
呼叫类型参数应该是String
阻塞型推理系统,所以它需要被明确指定。但为什么插入一个(承认冗余)演员搞砸了?
But why does inserting a (admittedly redundant) cast mess things up?
因为现在本身表达Collections.emptyList()
没有任何赋值的目标 - 所以应该选择什么类型的参数?这只是为了更好地指定类型参数:
// Redundant here, but just as an example
List<String> alwaysEmpty = Collections.<String>emptyList();
它适用于有条件的经营者一样,太:
public static void main(String[] args) {
List<String> list = (args != null)
? Arrays.asList(args) : Collections.<String>emptyList();
}
我要去接受乔恩的答案,但也希望列为答案这个外面有人传给我的是什么。这是提交给Sun/Oracle的关于这件事的bug report的链接。评估错误的人对发生的事情有一个有用的解释。摘录:
The submitter here seems to assume that the type of a conditional expression is the type on the LHS of an assigment (
List<String>
in this case). This is not true: as stated by the JLS, the type of a conditional expression:"The type of the conditional expression is the result of applying capture conversion (§5.1.10) to
lub(T1, T2)
(§15.12.2.7). "It's important to understand why it's necessary to apply lub. Consider the following example:
class A {}
class B extends A{}
class C extends A{}
class Foo<X>
Foo<? extends A> l = b ? new Foo<B>() : new Foo<C>()
In this case we have that LHS is of type
Foo<? extends A>
while the RHS is of typelub(Foo<B>, Foo<C>)
, that isFoo<? extends B&C>
.