The following code works when compiled with sourceCompatibility=1.7 or 1.6, but fails after switching to 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());
}
}
Compilation output:
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
Here's the repo with failing code: https://github.com/chalup/java8-wat. Just invoke ./gradlew clean build
from project directory.
I skimmed through JLS for Java 8, but I haven't found anything relevant.
Additional observation: the code compiles if I change the getParcelable()
signature to:
public Parcelable getParcelable()
Why does java compiler considers put(Serializable)
to be potentially applicable method for outBundle.put(inBundle.getParcelable())
call and what changes should be made to Parcelable/Bundle class? Bonus question: why does this error happens only on Java 8 and not on Java 7?
I would suggest that this is due to changes in how inference is done in java 8. And to the fact that Parcelable
is an interface.
Because of this, the infered return type of getParcelable
results in an ambiguous call because the infered return type can be applied to both methods.
I would mainly refer to this other question for a clearer explanation : Why can this generic method with a bound return any type?
As of to the real understanding of how the inference works in this specific case and why it is different between java 7 and 8, this would require a deeper study of the inference part of JLS.
As the Message says the reference to put is ambiguous
.
You have to explizity cast the value so that the compiler knows wich method you would like to use:
outBundle.put((Parcelable)Bundle.getParcelable());
or
outBundle.put((Serializable)Bundle.getParcelable());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With