2015-04-17 16 views
11

Poniższy kod działa, gdy skompilowany z sourceCompatibility = 1,7 lub 1,6, ale nie po włączeniu do 1,8:Dlaczego ten kod nie z sourceCompatibility = 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()); 
    } 
} 

Kompilacja wyjściowa:

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 

Oto repo z błędnym kodem: https://github.com/chalup/java8-wat. Wystarczy wywołać ./gradlew clean build z katalogu projektu.

Przeszedłem przez JLS dla Javy 8, ale nie znalazłem nic istotnego.

Dodatkowe obserwacje: kod kompiluje jeśli zmienić podpis getParcelable() do:

public Parcelable getParcelable() 

Dlaczego Java kompilator uzna put(Serializable) być potencjalnie stosowane metody outBundle.put(inBundle.getParcelable()) rozmowy i jakie zmiany należy wprowadzić do klasy Parcelable/Bundle ? Dodatkowe pytanie: dlaczego ten błąd występuje tylko w Java 8, a nie w Java 7?

+0

Powiązane: [Niejednoznaczna metoda w języku Java 8, dlaczego?] (Http://stackoverflow.com/questions/29499847/ambiguous-method-in-java-8-why) –

+0

Zamierzałem opublikować odpowiedź. No cóż. ; p – Radiodef

Odpowiedz

3

Sugerowałbym, że to ze względu na zmiany w sposobie wnioskowanie odbywa się w języku Java 8. I na fakt, że Parcelable jest interfejsem. Z tego powodu, zwracany typ zwrotu getParcelable powoduje wywołanie niejednoznaczne, ponieważ zwracany typ powrotu może być zastosowany do obu metod.

Chciałbym odnoszą się głównie do tej drugiej kwestii dla jaśniejszego wyjaśnienia: Why can this generic method with a bound return any type?

dzień do prawdziwego zrozumienia, w jaki sposób wnioskowanie działa w tym konkretnym przypadku i dlatego różni się między Java 7 i 8, byłoby wymagają głębszego studiowania JLS inference part.

+1

Działa w języku Java 7, ponieważ Java 7 tylko wywnioskowała argumenty typu na podstawie celu powrotu, jeśli podlegała konwersji przypisania. W przeciwnym razie górna granica zostanie wywnioskowana. Innymi słowy, fakt, że jedno połączenie jest wewnątrz drugiego, takie jak 'f (g()); 'jest przyczyną różnicy. W języku Java 7 "put (Serializable)" nie może być stosowane w ten sposób. – Radiodef

1

Zgodnie z treścią komunikatu reference to put is ambiguous.

Trzeba explizity cast wartość tak, że kompilator zna metody Wich chcesz użyć:

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

lub

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

To obejście problemu, ale chcę wiedzieć, dlaczego kompilator zakłada, że ​​typem zwrotnym 'getParcelable' jest' Serializable', co prowadzi do niejednoznaczności. – chalup

+1

, ale dlaczego istnieje różnica między wersją java 8 i wcześniejszymi? – eis

+2

Ta odpowiedź dotyczy tylko jednej części pytania dwóch (lub trzech) części. – Vulcan

Powiązane problemy