【问题标题】:Why is Java's type inference so weak?为什么 Java 的类型推断这么弱?
【发布时间】:2014-02-11 01:10:24
【问题描述】:

说,我有一个方法:

public static <T> Collection<T> addToCollection(T element, Collection<T> collection) {
    collection.add(element);
    return collection;
}

然后在尝试编译这段代码时:

Integer i = 42;
Collection<Integer> result = addToCollection(i, Collections.emptyList());

我收到一个错误Type mismatch: cannot convert from Collection&lt;Object&gt; to Collection&lt;Integer&gt;。 谁能解释为什么类型系统不能推断 Collections.emptyList() 应该是Collection&lt;Integer&gt; 类型?

上面的例子显然是很人为的,但我总是偶然发现这个限制,这真的很烦人。在阅读了 Effective Java 之后,我发现您可以简单地执行 Collections.&lt;Integer&gt;emptyList()(必须说,这在当时对我来说是一个相当大的启示)并且一切都可以顺利编译,但是当您有一些复杂的类型真的很麻烦。

我只是想知道这是否是某种错误,或者是否有任何正当理由让它以这种方式工作?

【问题讨论】:

  • 能否改写标题?
  • 谈论锅叫水壶黑色。 Collections.emptyList() 返回一个不可修改的列表,所以代码无论如何都不会工作。
  • @Kayaman 题外话,正如 OP 指出的那样。问题是关于推理的原则,运行时并没有考虑到它。
  • @MarkoTopolnik 我知道问题是什么,不要再光顾我了。我要指出的是,他在抱怨“迟钝”的类型推断时写了一个“迟钝”的例子。
  • @Kayaman 你在光顾 OP,这让你公平游戏。

标签: java generics type-inference


【解决方案1】:

Java 8 对类型推断系统进行了改进,引入了target typing,以便为流和 lambda 提供更多的表现力。因此,您的代码可以使用 Java 8 进行编译。

updated tutorial 中了解更多信息,页面底部有一个非常相似的示例。

【讨论】:

  • 直到!太棒了——在这些情况下,我自己在 javac 上喃喃自语。我明天必须试试这个(这台机器上没有 jdk 8)。如果我还期望这种更好的推理适用于三元组,我会感到失望吗? List&lt;String&gt; foo = myBool ? someList : Collections.emptyList()
  • @yshavit 也可以编译。
  • 许多年前,在史诗般的 BGGA/CICE/FCM 大战时,我读到 somewhere 说“Java 应该专注于修复其泛型,而不是引入另一层复杂性”。原来他们把前者作为对后者的服务:)
【解决方案2】:

Collections.emptyList() 返回一个List&lt;Object&gt;,它通过您的addToCollection() 方法传递。而且由于 Object 不是 Integer,因此失败了。

【讨论】:

  • 这不是真的。这是一个通用的方法。
  • &lt;T&gt; public static List&lt;T&gt; emptyList()---仅出于这个原因,作为常量EMPTY_LIST的方法包装器引入。
  • 这是一个泛型方法,但是有两个选项可以绑定泛型类型:基于参数或基于返回类型。在这里,显然绑定是基于您传入的第二个参数发生的。
  • Java(我们在下面的回复中指出,至少最多 7 个)只有在将方法分配给变量时才能正确推断方法的返回类型。例如。 List x = Collections.emptyList() 有效,但是如果您将 Collections.emptyList() 作为参数传递给某个方法,则没有推论。它默认返回对象。
【解决方案3】:

这样做有什么害处?

Integer i = 42;
List<Integer> emptyList = Collections.emptyList();
Collection<Integer> result = addToCollection(i, emptyList);

在 java 8 中它会被处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 2015-08-11
    • 2014-11-06
    • 2011-03-19
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多