以下代码在使用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
。
我浏览了JLS for Java 8,但我没有发现任何相关内容。
其他观察:如果我将getParcelable()
签名更改为:
public Parcelable getParcelable()
为什么java编译器认为put(Serializable)
是outBundle.put(inBundle.getParcelable())
调用的潜在适用方法,应该对Parcelable / Bundle类进行哪些更改?额外问题:为什么这个错误只发生在Java 8上而不发生在Java 7上?
答案 0 :(得分:3)
我建议这是因为在java 8中进行推理的方式发生了变化。Parcelable
是一个接口。
因此,getParcelable
的推理返回类型会导致调用不明确,因为推理返回类型可以应用于这两种方法。
我会主要参考另一个问题以获得更清楚的解释:Why can this generic method with a bound return any type?
至于真正理解推理如何在这个特定情况下工作以及为什么它在java 7和8之间有所不同,这需要对JLS的inference part进行更深入的研究。
答案 1 :(得分:1)
正如消息所说reference to put is ambiguous
。
你必须对值进行探索,以便编译器知道你想要使用的方法:
outBundle.put((Parcelable)Bundle.getParcelable());
或
outBundle.put((Serializable)Bundle.getParcelable());