2011-01-28 4 views

risposta

19

<typearg>methodname è la sintassi per specificare esplicitamente l'argomento tipo per un metodo generico

Quando si utilizza una classe generica, di solito si devono specificare il tipo di argomento (ad es String):

ArrayList<String> list = new ArrayList<String>(); 

Con un metodo generico, di solito non passa un tipo di argomento:

public static <T> void foo(T param) { } 
... 
String s = ...; 
MyClass.foo(s); 

Non noterai dove abbiamo fatto esplicitamente il codice specifica che vogliamo la versione String di foo, cioè non è stato specificato alcun argomento di tipo esplicito <String> come abbiamo visto quando si utilizza una classe generica (List<String>).

Il compilatore sta facendo qualche magia compilatore di dedurre l'argomento di tipo generico in base al contesto. Questa è una cosa grandiosa e molto potente.

Tuttavia, occasionalmente il compilatore non può dedurre automaticamente gli argomenti di tipo:

public static <T> void bar() { T myLocalVar = ...; ... } 
MyClass.bar(); 

Quale versione concreta del bar stiamo cercando di richiamare, vale a dire quello che è l'argomento tipo per questa chiamata? Boh? Bene, neanche il compilatore.Dobbiamo dichiarare esplicitamente l'argomento tipo, proprio come facciamo normalmente quando si utilizza una classe generica:

MyClass.<String>bar(); 

vedi anche:


parte: può essere utile ricordare che la Java 7 sarà aggiunta del cosiddetto operatore diamante per consentire di avere il compilatore di dedurre argomenti tipo utilizzando classi generiche ormai troppo:

ArrayList<String> list = new ArrayList<String>(); 

diventa

ArrayList<String> list = new ArrayList<>(); 

What is the point of the diamond operator in Java 7?

8

Questo è il modo di specificare in modo esplicito il parametro di tipo ad un metodo generico. Nella maggior parte dei casi, il compilatore può dedurlo, ma a volte deve essere esplicitamente indicato.

+0

Per mia stessa curiosità: è necessario dichiararlo esplicitamente perché questi metodi sono statici? – christophmccann

+1

@Christopher: no. Funziona sia con metodi statici che non statici. –

+0

Deve essere specificato esplicitamente perché è statico, quindi non esiste un costruttore che abbia corretto gli argomenti di tipo Generico e poiché gli argomenti di tipo Generico non possono essere desunti dall'elenco dei parametri. –

1

Le risposte di cui sopra praticamente rispondere alla sua domanda, ma se si vuole un esempio specifico di un caso in cui l'inferenza di tipo generico di Java non riesce e expli citamente affermando in questo modo salva la situazione, considerare le seguenti definizioni di classe:

public class A { } 
public class B extends A { } 
public class C extends A { } 

Poi il seguente codice funziona bene (vale a dire, l'inferenza dei tipi di Java riesce):

List<Class<? extends A>> list = ImmutableList.of(B.class, C.class); 

Ma per il seguente , non riesce a compilare:

List<Class<? extends A>> list = ImmutableList.of(B.class); 

Esatto; stranamente, da rimuovendo un parametro, confondiamo il sistema inferenza di tipo, dal momento che la 'più vicino discendente comune' di B.class e C.class è A.class, ma per B.class di per sé, è solo B.class, che (per mancanza di covarianza a generici di Java) non corrisponde a List<Class<? extends A>>. In questo caso, non hai scelta, ma per l'uso:

List<Class<? extends A>> list = ImmutableList.<Class<? extends A>>of(B.class); 

Dal B non effettivamente estendere A, questo compila (e funziona) più che bene.

Spero che questa dimostrazione enfatizzi l'utilità dell'operatore.

Problemi correlati