Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this code fail with sourceCompatibility=1.8 [duplicate]

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?

like image 222
chalup Avatar asked Apr 17 '15 06:04

chalup


2 Answers

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.

like image 116
benzonico Avatar answered Dec 07 '22 19:12

benzonico


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());
like image 27
Jens Avatar answered Dec 07 '22 20:12

Jens