【问题标题】:Java 7 generics type inference: return value vs method argumentJava 7 泛型类型推断:返回值与方法参数
【发布时间】:2013-03-15 15:07:04
【问题描述】:

为什么编译器能够在函数返回类型的情况下正确推断出String 类型参数。

public class Generics {
    private static List<String> function() {
        return new ArrayList<>();
    }
}

但是当要推断的类型是方法参数时它会失败:

public class Generics {
    public static void main(String[] args) {
        method(new ArrayList<>());
    }    

    private static void method(List<String> list) {

    }
}

这种情况下的错误是:

The method method(List<String>) in the type Generics is not applicable 
for the arguments (ArrayList<Object>)

【问题讨论】:

  • 因为他们不会在可能的情况下实现泛型类型推断。我没有测试过这个特定的案例,但是 Java 8 在类型推断方面带来了很多改进,以帮助使用 lambda。
  • 这是因为完美的类型推断是一个在有限时间内难以解决的问题(它与停机问题的复杂度相同)。因此,Java 开发人员不得不在某处划清界限。正如其他人所指出的那样,他们不断地把这条线推得更远,但必须存在一些限制。
  • @KonstantinNaryshkin:在 Java 8 上所做的工作表明他们很早就划清了界限。更多有用的规则可能的,并且正在被集成在 Java 8 中。说他们应该在第一次进一步推动它很容易,但很难预测哪些额外的工作有实际的好处。总而言之,最初的实现非常有用。但它本来可以更早改进的。

标签: java generics type-inference


【解决方案1】:

这是类型推断尚未按预期工作的地方之一。

不幸的是,这种行为是完全有效且符合要求的。

好消息是Java 8 将包含improved type inference (JEP 101),所以像这样的情况应该按照你的预期编译:

当这种泛型方法调用的结果被传递给另一个方法时,编译器应该能够推断出类型似乎是合理的 [...]。

不幸的是,这在 JDK 5/6/7 中是不允许的——程序员唯一可用的选择是使用显式类型参数。

除了直接改进(即您在此处提到的情况)之外,此更改对于能够更有效地使用Lambdas (JEP 126) 也是必要的(即无需输入大量类型信息)。

【讨论】:

  • 是的,他们写的例子基本完全相同。
  • 似乎 java 8 将是自 java 5 以来更大的 java 版本。我很不耐烦用它进行开发。这些还得用java 1.4的在我心里。
【解决方案2】:

JLS 中关于inferring unresolved type arguments 的部分相当复杂,但我知道第一种情况的菱形出现在需要赋值转换的地方,而在第二种情况下它发生在方法调用转换中,遵循不同的规则。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 2020-01-23
    相关资源
    最近更新 更多