【问题标题】:Why does this code fail with sourceCompatibility=1.8 [duplicate]为什么此代码因 sourceCompatibility=1.8 而失败 [重复]
【发布时间】:2015-04-17 06:56:28
【问题描述】:

以下代码在使用 sourceCompatibility=1.7 或 1.6 编译时有效,但在切换到 1.8 后失败:

public class Java8Wat {
  interface Parcelable {
  }

  static class Bundle implements Parcelable {
    public void put(Parcelable parcelable) {
    }

    public void put(Serializable serializable) {
    }

    public <T extends Parcelable> T getParcelable() {
      return null;
    }
  }

  static {
    Bundle inBundle = new Bundle();
    Bundle outBundle = new Bundle();

    outBundle.put(inBundle.getParcelable());
  }
}

编译输出:

Java8Wat.java:23: error: reference to put is ambiguous
        outBundle.put(inBundle.getParcelable());
             ^
both method put(Parcelable) in Bundle and method put(Serializable) in Bundle match

这是代码失败的仓库:https://github.com/chalup/java8-wat。只需从项目目录调用./gradlew clean build

我浏览了 Java 8 的 JLS,但没有找到任何相关内容。

补充观察:如果我将getParcelable() 签名更改为:

public Parcelable getParcelable()

为什么 java 编译器认为put(Serializable)outBundle.put(inBundle.getParcelable()) 调用的潜在适用方法,应该对 Parcelable/Bundle 类进行哪些更改?额外问题:为什么这个错误只发生在 Java 8 上而不发生在 Java 7 上?

【问题讨论】:

标签: java generics java-8


【解决方案1】:

我认为这是由于在 java 8 中进行推理的方式发生了变化。并且Parcelable 是一个接口这一事实。 因此,getParcelable 的推断返回类型会导致不明确的调用,因为推断的返回类型可以应用于这两种方法。

我主要参考这个其他问题以获得更清晰的解释:Why can this generic method with a bound return any type?

要真正理解推理在这种特定情况下的工作原理以及为什么它在 java 7 和 8 之间有所不同,这需要对 JLS 的inference part 进行更深入的研究。

【讨论】:

  • 它在 Java 7 中有效,因为 Java 7 仅在需要进行赋值转换时才根据返回目标推断类型参数。否则会推断出上限。换句话说,一个呼叫在另一个呼叫内部,例如f(g());,这就是存在差异的原因。在 Java 7 中,put(Serializable) 不能以这种方式适用。
【解决方案2】:

正如消息所说,reference to put is ambiguous

您必须明确地转换该值,以便编译器知道您想使用哪种方法:

outBundle.put((Parcelable)Bundle.getParcelable());

outBundle.put((Serializable)Bundle.getParcelable());

【讨论】:

  • 这是一种解决方法,但我想知道的是为什么编译器会假设getParcelable的返回类型是Serializable,这会导致歧义。
  • 但是为什么 java 8 和之前的有区别呢?
  • 这个答案只解决了两(或三)部分问题的一部分。
  • 如果我们谈论的是“我如何编译这段代码?”解决方法,显然更简洁的解决方案是向 getParcelable 调用添加显式类型参数。
  • @Jens 问题的主题不是一直都一样吗?这个答案没有解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2012-04-06
  • 1970-01-01
  • 2012-09-08
  • 2013-09-24
  • 2011-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多