2016-01-22 12 views
5

Sto cercando di imparare Java Generics e ho trovato il seguente codice.Si verificano errori durante la chiamata alla stampa (Elenco <T> a, T b) con diversa classe T

public static <T> void print(T a, T b){ 
    System.out.println(a); 
    System.out.println(b); 
} 

public static void main(String[] args){ 
    print(new ArrayList<String>(), 1); 
} 

Che funziona senza problemi.

Tuttavia, quando cambio il metodo print nel modo seguente, vengono visualizzati errori di compilazione.

public static <T> void print(List<T> a, T b){ 
    System.out.println(a); 
    System.out.println(b); 
} 

Errore:

GenericTest.java:9: error: method print in class GenericTest cannot be applied to given types; 
    print(new ArrayList<String>(), 1); 
    ^
    required: List<T>,T 
    found: ArrayList<String>,int 
    reason: no instance(s) of type variable(s) T exist so that argument type int conforms to formal parameter type T 
    where T is a type-variable: 
    T extends Object declared in method <T>print(List<T>,T) 
1 error 

Qualcuno può aiutarmi a capire gli errori?

risposta

8

La prima cosa che si dovrebbe capire è che, con la seguente firma del metodo

public static <T> void print(T a, T b) 

Entrambi Tdeve essere lo stesso tipo, vale a dire sia a e b avrà lo stesso tipo dedotto.

Quindi perché funziona per new ArrayList<String>() e 1? Poiché entrambi i parametri possono effettivamente essere rappresentati come Serializable, che è il più vicino eccellente tipo comune di ArrayList e Integer:

  • ArrayList implementa l'interfaccia Serializable.
  • 1 può essere inserito in un Integer, che è anche Serializable.

Quindi in questo caso il compilatore dedurrà T come Serializable.


Nel secondo caso, con la firma

public static <T> void print(List<T> a, T b) 

Non c'è comune super-tipo T che sarebbe valido sia per List<String> e Integer. È vero che sia String e Integer sono Serializable, ma dal generics aren't polymorphic, non funziona.

+0

si può spiegare anche il motivo per cui è deliberato di 'Serializable' e non qualsiasi altro tipo super-comune? – Codebender

+0

@Codebender Perché è il tipo super comune più vicino tra 'ArrayList' e' Integer'. 'Object' sarebbe un livello in alto nella gerarchia. – Tunaki

+0

Non capisco come si forma la gerarchia tra Interfaccia e Classe (farò una nuova domanda al riguardo), ma eclissi mostra che è stato risolto in Serializable (+1 per quello) ... – Codebender

5

Modifica: Non viene risolto in Oggetto come ho detto ma Serializable. See Tunaki's correct answer for the reason.

Nel primo caso, T è stato risolto nel tipo più specifico che può fare riferimento a entrambi gli argomenti.

E nel tuo esempio, otterrà deliberato di Object Serializable, dal momento che ArrayList e Integer sono entrambi i sottotipi Object Serializable.

Ma nel tuo secondo esempio, si dispone di un List<T> come parametro ...

Ora, quando si chiama con ArrayList<String>, il tipo T viene risolto in un String. Esso non può essere risolto a qualsiasi altro tipo perché un ArrayList<Object> ArrayList<Serializable> è NON un supertipo di ArrayList<String>

3

si chiama il metodo in modi seguenti:

print(new ArrayList<String>(), "SimpleString"); 

o

print(new ArrayList<Integer>(),5) 

perché <T> è un tipo e non può essere sia stringa e intero allo stesso tempo.

La chiamata potrebbe funzionare se si fa qualcosa di simile:

public static <T, K> void print(List<T> a, K b){ 
    System.out.println(a); 
    System.out.println(b); 
} 

public static void main(String[] args){ 
    print(new ArrayList<String>(),1); 
} 
+0

Questa è la migliore risposta in quanto è l'unica ad avere codice con 2 parametri di tipo. Poiché la sintassi non è necessariamente intuitiva per un principiante. L'esempio chiarisce come usarlo. Bel lavoro. +1 alla data di scadenza (limite di voto). – HopefullyHelpful

Problemi correlati