为什么参数化方法在某些情况下可以隐式绑定而不是其他情况?

Mar*_*der 4 java generics

我最近在重构代码时遇到了这个问题:

下面的方法"getList()"具有参数化的返回类型.在下面,我已经放了三个试图隐式绑定的<T>方法<Integer>.

我无法弄清楚为什么前两个编译和运行正确,而第三个(bindViaMethodInvocation)甚至不会编译.

有线索吗?

在StackOverflow上寻找类似的问题时,我遇到了这个问题: 返回类型的推断通配符泛型.那里的答案(信用Laurence Gonsalves)有几个有用的参考链接来解释应该发生的事情: "这里的问题(正如你的建议)是编译器正在执行捕获转换.我相信这是结果JLS的JLS 的§15.12.2.6."

package stackoverflow;

import java.util.*;

public class ParameterizedReturn
{
    // Parameterized method
    public static <T extends Object> List<T> getList()
    {
        return new ArrayList<T>();
    }

    public static List<Integer> bindViaReturnStatement()
    {
        return getList();
    }

    public static List<Integer> bindViaVariableAssignment()
    {
        List<Integer> intList = getList();
        return intList;
    }

    public static List<Integer> bindViaMethodInvocation()
    {
        // Compile error here
        return echo(getList());
    }

    public static List<Integer> echo(List<Integer> intList)
    {
        return intList;
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 7

前两个方法getList()在用于赋值转换的上下文中使用- List<Integer>从返回的方法赋值或返回语句List<Integer>.同样是不真正对bindViaMethodInvocation-使用表达式作为方法的参数是受到分配的转换.

JLS第15.12.2.8节:

如果没有从实际参数的类型推断出任何方法的类型参数,现在推断它们如下.

  • 如果方法结果发生在它将受到赋值转换(第5.2节)到类型S的上下文中,那么让R成为方法的声明结果类型,并让R'= R [T1 = B(T1) ...... Tn = B(Tn)]其中B(Ti)是上一节中Ti的推断类型,如果没有推断出类型,则推断Ti.

JLS不清楚为什么返回语句在这里计算.我能找到的最接近的是14.17:

带有Expression的return语句必须包含在声明为返回值(第8.4节)或发生编译时错误的方法声明中.Expression必须表示某种类型T的变量或值,否则会发生编译时错误.类型T必须可赋值(第5.2节)到方法的声明结果类型,否则会发生编译时错误.

(如果第5.2节指出,return语句这将是很好受分配转换).