Feu*_*mel 21 java generics ternary-operator bounded-wildcard
以下类定义了两种方法,两种方法都直观地具有相同的功能.使用两个类型列表List<? super Integer>和一个布尔值调用每个函数,该值指定应将哪些列表分配给局部变量.
import java.util.List;
class Example {
void chooseList1(boolean choice, List<? super Integer> list1, List<? super Integer> list2) {
List<? super Integer> list;
if (choice)
list = list1;
else
list = list2;
}
void chooseList2(boolean choice, List<? super Integer> list1, List<? super Integer> list2) {
List<? super Integer> list = choice ? list1 : list2;
}
}
Run Code Online (Sandbox Code Playgroud)
根据javac 1.7.0_45,chooseList1有效而chooseList2不是.它抱怨说:
java: incompatible types
required: java.util.List<? super java.lang.Integer>
found: java.util.List<capture#1 of ? extends java.lang.Object>
Run Code Online (Sandbox Code Playgroud)
我知道查找包含三元运算符(… ? … : …)的表达式类型的规则非常复杂,但据我所知,它选择了最具体的类型,第二个和第三个参数都可以在没有显式的情况下进行转换投.在这里,这应该是,List<? super Integer> list1但事实并非如此.
我想看看为什么不是这种情况的解释,最好是参考Java语言规范,并直观地解释如果没有阻止可能出错的地方.
Sot*_*lis 13
这个答案适用于Java 7.
否则,第二和第三操作数分别是S1和S2类型.设T1是将拳击转换应用于S1所产生的类型,让T2为应用到S2的装箱转换所产生的类型.
条件表达式的类型是将捕获转换(第5.1.10节)应用于lub(T1,T2)(第15.12.2.7节)的结果.
在表达中
List<? super Integer> list = choice ? list1 : list2;
Run Code Online (Sandbox Code Playgroud)
T1是List<capture#1? super Integer>和T2是List<capture#2? super Integer>.这两者都有下限.
本文详细介绍了如何计算lub(T1, T2)(或join function).我们来自那里
<T> T pick(T a, T b) {
return null;
}
<C, A extends C, B extends C> C test(A a, B b) {
return pick(a, b); // inferred type: Object
}
void tryIt(List<? super Integer> list1, List<? super Integer> list2) {
test(list1, list2);
}
Run Code Online (Sandbox Code Playgroud)
如果您使用IDE并将鼠标悬停在上面test(list1, list2),您会注意到返回类型是
List<? extends Object>
Run Code Online (Sandbox Code Playgroud)
这是Java类型推断可以做的最好的.如果list1是a List<Object>并且list2是a List<Number>,唯一可接受的返回类型是List<? extends Object>.由于必须涵盖此案例,因此该方法必须始终返回该类型.
同样地
List<? super Integer> list = choice ? list1 : list2;
Run Code Online (Sandbox Code Playgroud)
该lub(T1, T2)又是List<? extends Object>和它的捕获转换List<capture#XX of ? extends Object>.
最后,类型的引用List<capture#XX of ? extends Object>不能分配给类型的变量,List<? super Integer>因此编译器不允许它.