调用java泛型方法

时间:2011-06-30 13:01:25

标签: java generics

给出通用方法:

<T> List<T> getGenericList(int i) {...}

以下代码编译时没有任何警告:

public List<String> getStringList(boolean b){
    if(b)
        return getGenericList(0);
    else
        return getGenericList(1);
}

但是这个会生成'Type mismatch'编译错误:

public List<String> getStringList(boolean b) {
    return (b) ? getGenericList(0) : getGenericList(1);
}

为什么?

5 个答案:

答案 0 :(得分:7)

这是不是泛型问题,而是编译器必须推断三元表达式类型的结果。

这个等效代码也是如此。此代码有效:

public byte function(boolean b){
    if(b)
        return 1;
    else
        return 2;
}

虽然不是这样:

public byte function(boolean b) {
    return (b) ? 1 : 2;
}

原因是当编译器尝试推断该表达式的类型时

    return (b) ? 1 : 2;

首先必须获取每个操作数的类型,并检查它们是否兼容(reference)以评估三元表达式是否有效。 如果“返回”的类型被传播以自动转换或提升每个操作数,则可能会导致根据上下文这个表达。

鉴于“return”的类型无法传播到操作数,那么在所提到的案例中:

    return (b) ? getGenericList(0) : getGenericList(1);

无法完成泛型类型的绑定,因此每个操作数的类型都解析为List<Object>。然后编译器得出结论:整个表达式的类型是List<Object>,不能自动转换为List<Integer>(因为它们不兼容类型)。

而另一个

    return getGenericList(0);

它应用“return”的类型来绑定泛型类型T,因此编译器断定表达式具有List<String>类型,可以安全返回。

答案 1 :(得分:5)

当评估三元运算符时,它的结果不受任何类型的约束。这就像你打电话:

getGenericList(0);

尝试编译以上内容,编译将失败。

在return语句中,结果绑定到函数的返回类型并进行求值。

修改

我错了。上面的语句编译,但结果类型被评估为(List&lt; Object&gt;)。尝试编译:

List<String> l = (List<String>)getGenericList(0);

这个会失败。

答案 2 :(得分:5)

这是因为泛型类型推导的边缘情况

在显式返回中,每个getGenericList的返回类型可以简单地设置为List(向外信息向内传播)

但是在条件中它走另一种方式它的类型是两种可能性中更一般的(向内信息向外传播)

编译器可以在这里隐式地扣除信息,但是如果你确实需要的话,它还没有构建错误报告

答案 3 :(得分:2)

这是因为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

但是这种方法无论如何都是危险的。您的方法怎么知道是时候返回List<String>,而不是其他内容的列表?没有关于T可用的信息。

答案 4 :(得分:1)

看起来它只是效率低下的编译。

正如Maurice所说,通常,编译器通过函数参数确定T的类型。在这种情况下,没有任何。

但是,因为getStringList()返回List<String>并且它调用return getGenericList(),所以编译器足够聪明,可以将getStringList的返回类型转发到getGenericList,并以这种方式确定类型。

我的猜测是,在三元运算符中,它不会反向绑定,而是在每个子语句中找到公分母并将其指定为三元语句的输出,并且编译器不够智能不能通过三元语句的预期输出到其子语句中。

注意,你可以直接将type参数传递给函数调用,它工作正常,即:

return b ? this.<String> getGenericList(0) : this.<String> getGenericList(1);

正确编译。