鉴于此通用功能:
<T> List<T> function() { return null; }
为什么要编译
List<String> l = function();
虽然这不是?
List<String> l = (List<String>) function();
答案 0 :(得分:8)
因为你做这样的演员:
(List<String>) function()
编译器无法推断function()
调用的类型参数,而是依赖绑定T
到Object
。
在
中List<String> l = function();
可以推断出T
的正确类型。
请注意,如果您通过明确提供类型来规避类型推断的工作,则可以强制转换:
import java.util.List;
class Test {
public static <T> List<T> function() { return null; }
public static void main(String[] args) {
List<String> l = (List<String>) Test.<String>function();
// ^^^^^^^^^^^^^
}
}
我不知道通用参数的确切类型推理规则。但是,它们在JLS Section 15.12.2.7中指定。
答案 1 :(得分:2)
在尝试强制转换后(编译器)看起来类似推断。
表达式的类型由表达式的左侧确定,在尝试强制转换时尚未“解析”。转换本身也会失败,因为对于尚未推断的类型,结果(方法调用)的类型为List<Object>
JLS的15.12.2.7部分表明类型推断最后发生。
答案 2 :(得分:1)
第一个使用类型推断,使用分配结果的变量类型。
在第二个中,调用的结果未分配给任何内容(在完成强制转换之前),因此返回最通用的类型(List<Object>
),List<Object>
可以'被投射到List<String>
。
答案 3 :(得分:1)
这是因为javac需要推断T,但T不会出现在参数类型中。
static<T> T foo(){ .. }
foo(); // T=?
只有在2种情况下,javac才能从上下文中推断出T
String s = foo(); // #1: assignment
String bar(){
return foo(); // #2: return
在其他情况下,javac不会,而T只是推断为Object
答案 4 :(得分:0)
List<String>
不会延伸List<Object>
。所以你不能施展它。
您可以在下一个方向指定T
List<String> l = this.<String>function();
答案 5 :(得分:0)
那是因为编译器无法推断方法function()
的参数化类型,因此它将T
绑定到Object
。您无法将List<Object>
投射到List<String>
。
答案 6 :(得分:0)
问题不确切。
List<String> m = (List<String>)function();
生成警告&#34;类型安全:未选中从对象到列表的强制转换&#34;这是正确的,因为对泛型类型的所有强制类型都是不安全的。