2015-11-17 10 views
16

Qual è la differenza tra:metodo generico Java 6 <T> prima tipo di ritorno

public <T> void createArray(T sample){ 
    ArrayList<T> list = new ArrayList<T>(); 
    list.add(sample); 
} 

e

public void createArray(T sample){ 
    ArrayList<T> list = new ArrayList<T>(); 
    list.add(sample); 
} 

ho letto che la firma del metodo per l'utilizzo di tipi dovrebbe avere <T> prima che il tipo di ritorno, ma come come sono ancora in grado di creare il metodo senza il <T>? Qual è l'implicazione se lo faccio o non lo metto?

+6

La risposta data sono probabilmente ragione, ma si noti che, così com'è, il vostro 'createArray' nel secondo frammento di non viene compilato. – Tunaki

risposta

20

Nel secondo metodo, il parametro di tipo sarebbe tipicamente definito nella dichiarazione della classe a cui appartiene il metodo:

class MyClass<T> { 
    public void createArray(T sample){ 
     ArrayList<T> list = new ArrayList<T>(); 
     list.add(sample); 
    } 
    ... 
} 

Quindi il secondo metodo appartiene a un tipo generico. Il primo metodo è un metodo perché definisce il proprio parametro di tipo.

8

Nel primo caso, per il metodo viene definito il parametro generico T. Altri metodi possono avere un diverso T.

Nel secondo caso, il parametro generico T è definito per la classe o l'interfaccia. Tutti i metodi all'interno di quella classe o interfaccia devono avere lo stesso T.

Definire un generico a livello di classe consente di applicare lo stesso parametro di tipo su molti metodi. Puoi anche avere campi del tipo generico. Vedere ArrayList<t> per un esempio.

6

Dal secondo esempio, sto indovinando questo metodo viene definito in una classe qualcosa di generico come questo:

class SomeClass<T> { 
    public void createArray(T sample){ ... } 
} 

La differenza tra il primo e il secondo esempio è che nel primo esempio, il T è efficace una variabile di tipo "locale". Potresti dargli un nome diverso, ad es. S, per renderlo un po 'più chiaro:

class SomeClass<T> { 
    public <S> void createArray(S sample){ ... } 
} 

Così, S e T sono entrambe le variabili di tipo, ma sono indipendenti. T è definito nell'ambito della classe e quindi può essere utilizzato per fare riferimento allo stesso tipo tra tutti i metodi della classe; S è definito solo nell'ambito del metodo.

Utilizzando il nome T anziché S, si nasconde la variabile del tipo di livello di classe, T. Questo significa che, per esempio, la seguente non funzionerebbe:

class SomeClass<T> { 
    public T getWotsit() { ... } 
    public <T> void createArray(T sample){ 
    T wotsit = getWotsit(); 
    } 
} 

perché il T nella firma del getWotsit e T nella dichiarazione di variabili T wotsit potenzialmente riferiscono a differenti tipi; questo è più chiaro se si utilizza il nome S di scrivere il codice equivalente:

class SomeClass<T> { 
    public T getWotsit() { ... } 
    public <S> void createArray(S sample){ 
    S wotsit = getWotsit(); 
    } 
} 

Per quanto io sappia, non c'è modo di fare riferimento alla variabile di tipo a livello di classe se hai definito un variabile di tipo method-level con lo stesso nome.

Tuttavia, entrambi i seguenti andrebbe bene:

class SomeClass<T> { 
    public T getWotsit() { ... } 
    // No additional type variable, so T is the class-level type variable. 
    public void createArray(T sample){ 
    T wotsit = getWotsit(); 
    } 
} 

class SomeClass<T> { 
    public T getWotsit() { ... } 
    // Type variable has different name, so `T` is the class-level 
    // type variable. 
    public <S> void createArray(T sample){ 
    T wotsit = getWotsit(); 
    } 
} 
Problemi correlati