鉴于通用方法:
<T> List<T> getGenericList(int i) {...}
Run Code Online (Sandbox Code Playgroud)
以下代码编译时没有任何警告:
public List<String> getStringList(boolean b){
if(b)
return getGenericList(0);
else
return getGenericList(1);
}
Run Code Online (Sandbox Code Playgroud)
但是这个生成'Type mismatch'编译错误:
public List<String> getStringList(boolean b) {
return (b) ? getGenericList(0) : getGenericList(1);
}
Run Code Online (Sandbox Code Playgroud)
为什么?
这不是泛型问题,而是编译器必须推断三元表达式类型的结果.
这个等效代码也是如此.此代码有效:
public byte function(boolean b){
if(b)
return 1;
else
return 2;
}
Run Code Online (Sandbox Code Playgroud)
虽然这不是:
public byte function(boolean b) {
return (b) ? 1 : 2;
}
Run Code Online (Sandbox Code Playgroud)
原因是编译器尝试推断此表达式的类型时
return (b) ? 1 : 2;
Run Code Online (Sandbox Code Playgroud)
首先必须获取每个操作数的类型,并检查它们是否兼容(参考)以评估三元表达式是否有效.如果传播"return"的类型以自动转换或提升每个操作数,则可能导致根据此表达式的上下文以不同方式解析三元表达式的类型.
鉴于"返回"的类型不能传播到操作数,那么在所提到的情况下:
return (b) ? getGenericList(0) : getGenericList(1);
Run Code Online (Sandbox Code Playgroud)
无法完成泛型类型的绑定,因此解析了每个操作数的类型List<Object>
.然后编译器断定整个表达式的类型是List<Object>
,它不能自动转换为List<Integer>
(因为它们不是兼容的类型).
而另一个
return getGenericList(0);
Run Code Online (Sandbox Code Playgroud)
它应用"return"的类型来绑定泛型类型T,因此编译器断定表达式具有List<String>
可以安全返回的类型.
当评估三元运算符时,它的结果不受任何类型的约束.这就像你打电话:
getGenericList(0);
Run Code Online (Sandbox Code Playgroud)
尝试编译上面的内容,编译将失败.
在return语句中,结果绑定到函数的返回类型并进行求值.
编辑:
我错了.上面的语句编译,但结果类型计算为(List <Object>).尝试编译:
List<String> l = (List<String>)getGenericList(0);
Run Code Online (Sandbox Code Playgroud)
这个会失败.
这是因为泛型类型推导的边缘情况
在显式返回中,每个的返回类型getGenericList
可以简单地设置为List(向外信息向内传播)
但在有条件的情况下它走另一种方式它的类型是两种可能性中更一般的(向内信息向外传播)
编译器可以在这里隐式地扣除信息但是如果你确实需要的话,它还没有构建错误报告
归档时间: |
|
查看次数: |
448 次 |
最近记录: |