2015-03-27 25 views
5

Non riesco a risolvere questo problema su Google. Perché questa riga produrrebbe un errore di compilazione.Codice con generici non verrà compilato

wrapper.doSmth(wrapper.getCurrent()); 

sto usando Java 7.

public class App { 
Wrapper<?> wrapper; 

class Generic<T>{ 

} 

class Wrapper<T>{ 
    Generic<T> current; 

    public void doSmth(Generic<T> generic){ 
    } 

    public Generic<T> getCurrent(){ 
    return current; 
    } 
} 

public void operation(){ 
    wrapper.doSmth(wrapper.getCurrent()); 
} 
} 

L'errore è:

Error:(25, 24) java: method doSmth in class App.Wrapper<T> cannot be applied to given types; 
    required: App.Generic<capture#1 of ?> 
    found: App.Generic<capture#2 of ?> 
    reason: actual argument App.Generic<capture#2 of ?> cannot be converted to conf.App.Generic<capture#1 of ?> by method invocation conversion 
+3

È possibile pubblicare l'errore di compilazione effettivo? – Waterbagel

+1

@Waterbagel Ho modificato il mio post per includere un messaggio di errore – doctorgester

+0

E forse potresti dirci che cosa dovrebbe essere questo codice; quale problema intendi risolvere. – GhostCat

risposta

8

l'errore di compilazione dovrebbe essere qualcosa sulla falsariga di "cattura di # 1 non lo è? compatibile con capture of? # 2 ". La causa di questo errore è che wrapper è un Wrapper<?>.

Il compilatore vede che la wrapper.getCurrent() restituisce un Generic<?>, e che wrapper.doSmth prende un Generic<?> come parametro. Ma non equivale ai due caratteri jolly ?, anche se possiamo vedere che provengono dalla stessa istanza e dovrebbero essere uguali.

Una soluzione consiste nel rendere la classe App generica, in modo da poter sostituire il carattere jolly.

public class App<T> { 

A causa del fatto che Generic e Wrapper sono classi interne, T è ancora in campo di applicazione, in modo che non c'è bisogno di dichiarare un parametro di tipo generico per loro più.

Wrapper wrapper; 

    class Generic{ 

    } 

    class Wrapper{ 
     Generic current; 

     public void doSmth(Generic generic){ 
     } 

     public Generic getCurrent(){ 
      return current; 
     } 
    } 

    public void operation(){ 
     wrapper.doSmth(wrapper.getCurrent()); 
    } 
} 
+0

"Ma non equivale ai due? Caratteri jolly, anche se possiamo vedere che provengono dalla stessa istanza e dovrebbero essere uguali." Questo era lo scopo della mia domanda. C'è qualche logica dietro a questo? – doctorgester

+0

Il '?' Potrebbe essere qualsiasi cosa, in qualsiasi momento. In teoria, qualcosa potrebbe scambiare la "corrente" con qualcosa che ha un parametro di tipo completamente diverso. Forse quel qualcosa potrebbe essere un thread che rende questo compito durante 'operazione'. tl; dr Due '' 's non possono mai essere equivalenti. – rgettman

+0

Beh, quella era l'unica cosa che ho pensato. Non sono molto contento di questo. Grazie gentile signore! – doctorgester

1

Potrebbe essere un lavoro per un capturing helper.

public void operation() { 
    operationImpl(wrapper); 
} 

private static <T> void operationImpl(Wrapper<T> wrapper) { 
    wrapper.doSmth(wrapper.getCurrent()); 
} 

Nessun'altra modifica richiesta. L'helper cattura il tipo di wrapper in modo che possiamo essere certi che getCurrent restituisce lo stesso tipo di doSmth accetta.


La ragione questo errore accade è che ogni volta che un tipo con un carattere jolly viene indicato, un tipo distinto si presume per quel punto specifico nell'espressione (chiamato 'cattura'):

Wrapper<?> wrapper = ...; 

// each capture for T is assumed distinct from each other 
// vvvvvvv  vvvvvvv 
    wrapper.doSmth(wrapper.getCurrent()); 

Il fatto che i riferimenti facciano riferimento alla stessa istanza è irrilevante rispetto al modo in cui viene specificata l'acquisizione. Il compilatore non è necessario per tenere conto di questo e qualcosa di simile può accadere anche

Wrapper<?> wrapper = new Wrapper<String>(); 
wrapper.doSmth((wrapper = new Wrapper<Float>()).getCurrent()); 

dove T può cambiare mid-espressione.

Problemi correlati