2014-11-27 8 views
9

Ho visto questo codice oggi:Cosa significa l'operatore punto `.` (prima del parametro generico)?

ImmutableMap<Class<? extends ClientCommand>, CommandProcessorInterface> immutableMap = 
      ImmutableMap.<Class<? extends ClientCommand>, CommandProcessorInterface>of(... 

Che cosa significa questa sintassi?

ImmutableMap.<Class ..

sapevo farmaci generici è stato subito dopo il nome della classe. No?

Qual è la differenza tra:

ImmutableMap<Class.. e ImmutableMap.<Class..

+2

E 'parametri generici per metodo statico ' di ', non per la classe stessa. –

risposta

17

Significa che stai invocare un metodo statico generico, chiamato of nella classe ImmutableMap.

è più o meno lo stesso che si sta invocando un metodo static, annidato in qualche classe:

SomeClass.staticMethod(); 

Per i casi in cui il metodo ha un tipo-parametro definito, è in grado di fornire in modo esplicito il tipo generico e questo è fatto in questo modo:

SomeClass.<Type>genericStaticMethod(); 

e per rispondere si domanda finale:

Qual è la differenza tra ImmutableMap<Class...> e ImmutableMap.<Class...?

Il primo è solitamente utilizzato durante la creazione di un'istanza di una classe generica. È usato per definire il tipo generico a livello di classe, mentre il secondo è usato per invocare un metodo statico generico che è annidato in qualche classe.

+3

In genere non è necessario fornirlo. Vedi i [documenti] (https://docs.oracle.com/javase/tutorial/extra/generics/methods.html). 'fromArrayToCollection (sa, cs); // T inferito come String' – aalku

+2

Potrebbe essere dedotto dal tipo di ritorno cast (o assegnazione) ma non è sempre possibile. Dico solo "_hai bisogno di fornire il tipo generico_" non è sempre vero – aalku

+3

@ user270349 Direi che l'affermazione "devi" è semplicemente sbagliata. – xehpuk

2

Riguarda un metodo statico ImmutableMap.of. Questo ha i suoi parametri di tipo generico.

class Test { 

static <T> T f() { return null; } 

void t() { 
    String s = Test.f();     // Inferred from LHS. 
    String t = Test.<String>f();   // Not needed. 
    int n = Test.<String>f().length(); // Needed. 
} 

Nel tuo caso, non sembra davvero bisogno, ma ci sono su ghiaccio sottile, come l'inferenza di tipo generico è diventato un po 'più forte in Java 8.

2

metodi generici sono metodi dichiarati con qualsiasi tipo generico parametro. Vedere documento here. Il tipo generico del metodo non deve essere correlato a nessun parametro di tipo generico della classe dichiarante. La classe può o non può essere generica.

Quando si richiama un metodo generico (statico o meno), è possibile specificare il tipo generico ma di solito non lo si vede perché di solito è rilevato automaticamente. Quella sintassi che hai trovato è quella che lo specifica.

Se c'è un metodo dichiarato come questo:

<T> void fromArrayToCollection(T[] a, Collection<T> c) { ... 

si può chiamare in questo modo:

Integer[] a = ... 
ArrayList<Integer> l = ... 
x.fromArrayToCollection(a, l); 

ma se avete uno come questo:

<T> Collection<T> myMethod(int c) { 
    return new ArrayList<T>(c); 
} 

Quindi hai due modi per chiarire il tipo al compilatore. Puoi dargli abbastanza informazioni in due modi.

Uno si specifica il tipo di chiamata:

Object c = x.<Integer>myMethod(5); 

L'altro è con un typecast (esplicita o implicita assegnando ad una variabile):

Collection<Integer> c = x.myMethod(5);