为什么此代码在sourceCompatibility = 1.8时失败

cha*_*lup 11 java generics java-8

使用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());
  }
}
Run Code Online (Sandbox Code Playgroud)

编译输出:

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
Run Code Online (Sandbox Code Playgroud)

这是代码失败的回购:https://github.com/chalup/java8-wat.只需./gradlew clean build从项目目录中调用即可.

我浏览了JLS for Java 8,但我没有发现任何相关内容.

附加观察:如果我将getParcelable()签名更改为以下代码,则编译代码:

public Parcelable getParcelable()
Run Code Online (Sandbox Code Playgroud)

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

ben*_*ico 3

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

我主要参考另一个问题以获得更清晰的解释:为什么这个带有绑定的泛型方法可以返回任何类型?

至于真正理解在这个特定情况下推理是如何工作的以及为什么它在 java 7 和 8 之间不同,这需要对JLS 的推理部分进行更深入的研究。


归档时间:

查看次数:

330 次

最近记录:

10 年,6 月 前