2015-04-17 11 views
11

Il seguente codice funziona quando si compila con sourceCompatibility = 1.7 o 1.6, ma non riesce dopo il passaggio a 1,8:Perché questo codice non riescono con 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()); 
    } 
} 

Compilation uscita:

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 

Ecco il repository con codice in errore: https://github.com/chalup/java8-wat. Basta invocare ./gradlew clean build dalla directory del progetto.

Ho sfogliato JLS per Java 8, ma non ho trovato nulla di rilevante.

Ulteriori osservazione: il codice viene compilato se cambio la firma getParcelable() a:

public Parcelable getParcelable() 

Perché il compilatore java considera put(Serializable) ad essere metodo potenzialmente applicabili per outBundle.put(inBundle.getParcelable()) chiamata e quali cambiamenti dovrebbe essere fatto per classe Parcelable/Bundle ? Domanda bonus: perché questo errore si verifica solo su Java 8 e non su Java 7?

+0

Correlato: [Metodo ambiguo in Java 8, perché?] (Http://stackoverflow.com/questions/29499847/ambiguous-method-in-java-8-why) –

+0

Stavo per pubblicare una risposta. Oh bene. ; p – Radiodef

risposta

3

vorrei suggerire che ciò è dovuto a cambiamenti nel modo in cui l'inferenza è fatta in java 8. E sul fatto che Parcelable è un'interfaccia. Per questo motivo, il tipo restituito di getParcelable restituisce una chiamata ambigua poiché il tipo di ritorno inferito può essere applicato a entrambi i metodi.

mi richiamo principalmente a quest'altra domanda per una spiegazione più chiara: Why can this generic method with a bound return any type?

partire alla reale comprensione di come l'inferenza funziona in questo caso specifico e perché è differente tra Java 7 e 8, questo sarebbe richiede uno studio più approfondito di inference part di JLS.

+1

Funziona in Java 7 perché Java 7 ha inferito solo argomenti tipo basati su un target di ritorno se era soggetto alla conversione di assegnazione. Altrimenti il ​​limite superiore viene inferito. In altre parole, il fatto che una chiamata sia all'interno dell'altro come 'f (g()); 'è il motivo per cui c'è una differenza. In Java 7, 'put (Serializable)' non può essere applicabile in questo modo. – Radiodef

1

Come dice il messaggio reference to put is ambiguous.

Devi explizity cast del valore in modo che il compilatore sa metodo di wich si desidera utilizzare:

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

o

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

Questa è una soluzione, ma quello che voglio sapere è perché il compilatore presume che il tipo restituito di 'getParcelable' è' Serializable', che porta all'ambiguità. – chalup

+1

ma perché c'è differenza tra java 8 e precedenti? – eis

+2

Questa risposta riguarda solo una parte della domanda di parte due (o tre). – Vulcan

Problemi correlati