Java泛型类型绑定。为什么不编译?

时间:2011-06-30 13:46:20

标签: java generics

鉴于此通用功能:

<T> List<T> function() { return null; }

为什么要编译

List<String> l = function();

虽然这不是

List<String> l = (List<String>) function();

7 个答案:

答案 0 :(得分:8)

因为你做这样的演员:

(List<String>) function()

编译器无法推断function()调用的类型参数,而是依赖绑定TObject

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;这是正确的,因为对泛型类型的所有强制类型都是不安全的。