2011-12-20 15 views
9

Mi sono imbattuto in qualcosa che non capisco. Perché il valore di ogni ciclo non è legale quando il secondo è identico?Java Generics e tipi di reso

public interface SomeInterface<T> { 
    List<SomeNamedObject> getObjects(); 
    void doSomething(P1 p1, T p2); 
} 

public class SomeNamedObject { 
    private String text; 
} 

public class Clazz { 

    private SomeInterface someInterface; 

    ... 

    public void someMethod() { 
     // Error Type mismatch: cannot convert from element type Object to TestClass.SomeNamedObject 
     for (SomeNamedObject someNamedObject : someInterface.getObjects()) { 
      // This loop won't compile as the someInterface.getObjects returns just a List and not a List<SomeNamedObject> 
     } 

     // Warning Type safety: The expression of type List needs unchecked 
     // conversion to conform to List<TestClass.SomeNamedObject> 
     List<SomeNamedObject> objects = someInterface.getObjects(); 
     for (SomeNamedObject someNamedObject : objects) { 
      // This loop compiles 
     } 
    } 
} 
+0

Non è un bug, è un problema con la cancellazione e i tipi non elaborati. – Stefan

+0

Non vedo quale potrebbe essere il problema. Puoi pubblicare la traccia dello stack reale (solo le prime righe). Immagino che la tua classe completa richieda "SomeInterface ", ma l'esempio non richiede "" Forse c'è qualcosa in là? – Jay

+1

@Jay la sua dichiarazione di someInterface non specifica il tipo generico, Java quindi ricade sui tipi non elaborati e le modifiche alla firma del metodo per restituire un elenco non elaborato (vedere le risposte). Avrebbe dovuto menzionare l'avvertimento sull'assegnazione degli oggetti. – Stefan

risposta

18

Poiché l'istanza variabile private SomeInterface someInterface non specificare il parametro di tipo generico, allora tutto l'uso dei farmaci generici è disabilitata per someInterface. Ciò significa che someInterface.getObjects() ha il tipo di reso non elaborato List anziché List<SomeNamedObject>. Questo è il motivo per cui il primo esempio non viene compilato.

Nel secondo esempio, List<SomeNamedObject> objects = someInterface.getObjects() inserisce un tipo esplicito per l'elenco. Vedrai un avvertimento quando lo fai, anche perché la sicurezza del tipo non è garantita. Questo è lo stesso comportamento che si vedrebbe se getObjects() fosse definito come solo List getObjects() senza il parametro type.

+0

Potrebbe essere un errore di battitura nell'originale, ma 'SomeInterface ' non usa 'T' per specificare il tipo generico per il' List' che viene restituito, che è hardcoded come 'SomeNamedObject'. Quindi, anche se la variabile di istanza non è stata digitata, non dovrebbe influenzare il 'Elenco' restituito. –

+5

Se il parametro generico non è specificato nella dichiarazione di 'someInterface', i tipi * tutti * generici in' SomeInterface' vengono ignorati/disabilitati anche se non dipendono da 'T'. – mikej

+0

Molto interessante, anche se particolare. –

3

Si noti che viene visualizzato un avviso del compilatore quando si accede agli oggetti prima del secondo ciclo.

Type safety: The expression of type List needs unchecked conversion to conform to 
List<TestClass.SomeNamedObject> 

Questo ti avrebbe detto che per qualche motivo il metodo getObjects() restituisce un elenco non generato. Questo spiega perché il primo ciclo non si compila.

Perché ti sei dimenticato di generify vostro riferimento:

private SomeInterface someInterface; 

Se non generify che tutto utilizzerà il tipo grezzo, compresa la firma del metodo dichiarato. Significa che restituisce un oggetto elenco grezzo invece di una lista <SomeNamedObject> fare qualcosa di simile

private SomeInterface<Object> someInterface; 

e dovrebbe funzionare.