2013-03-31 11 views
6

Non capisco perché questo confonde il compilatore. Sto utilizzando il tipo generico T per contenere un oggetto che non è correlato ai metodi put e get. Ho sempre pensato che GenericClass e GenericClass<Object> fossero funzionalmente identici, ma devo sbagliarmi. Quando compilo la classe DoesntWork ottengo incompatible types - required: String - found: Object. La classe Works fa quello che mi aspetto. Cosa sta succedendo qui?Perché questa classe si comporta diversamente quando non fornisco un tipo generico?

public class GenericClass<T> { 
    public <V> void put(Class<V> key, V value) { 
     // put into map 
    } 

    public <V> V get(Class<V> key) { 
     // get from map 
     return null; 
    } 

    public static class DoesntWork { 
     public DoesntWork() { 
      GenericClass genericClass = new GenericClass(); 
      String s = genericClass.get(String.class); 
     } 
    } 

    public static class Works { 
     public Works() { 
      GenericClass<Object> genericClass = new GenericClass<Object>(); 
      String s = genericClass.get(String.class); 
     } 
    } 
} 
+0

'genericClass' è più vicino a' genericClass 'rispetto a' genericClass ' –

+0

Ciò detto, non riesco a capire perché' DoesntWork' non dovrebbe funzionare. –

+1

Provate a forzare il tipo: 'genericClass. get (String.class) '(non è sicuro che sia la sintassi corretta) –

risposta

8

La cosa su come tipi prime funzionano - tipi generici che hai lasciato fuori gli argomenti a favore - è che tutti i farmaci generici per loro ed i loro metodi sono cancellati pure. Quindi per un grezzo GenericClass, i metodi get e putanche perdono i loro generici.

+0

Perché dovrebbero? –

+0

L'uso di tipi non elaborati è, in sostanza, un'indicazione che stai usando un codice pre-generico legacy, ai fini della compatibilità; la maggior parte delle stranezze nei confronti dei tipi non elaborati sono gli hack a scopo di compatibilità. [JLS 4.8] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.8) ha più dettagli. –

+2

Ma per un esempio del perché questo comportamento specifico è necessario, si consideri il seguente esempio: il codice legacy costruito con Java 1.4 deve ottenere lo stesso comportamento da 'List' da Java 1.4 - pre-generici - e da' List' da Java 5, che è stato riscritto per introdurre i generici. È imbarazzante, ma necessario per la compatibilità con le versioni precedenti, ma non dovrebbe mai essere un problema per il nuovo codice, dal momento che il nuovo codice dovrebbe in pratica non utilizzare mai i tipi non elaborati. –

1

Questo perché quando si lavora con una classe generica senza le informazioni di tipo aggiuntive si lavora con quello che a volte viene chiamato il modulo degenerate della classe. Il modulo degenerate ha TUTTE le informazioni di tipo generico rimosse.

In sostanza - la classe diventa qualcosa di simile a:

comportamento
public class GenericClass { 
    public void put(Class key, Object value) { 
     // put into map 
    } 

    public Object get(Class key) { 
     // get from map 
     return null; 
    } 

    ... 
} 

La risposta compilatore che state vedendo è quindi previsto.

E 'menzionato in un Java Puzzlers.

Problemi correlati