Tutto ciò che sappiamo è " Tutte le istanze di una qualsiasi classe condividono lo stesso oggetto java.lang.Class di quel tipo di classe "
per esempio)
Student a = new Student();
Student b = new Student();
Quindi a.getClass() == b.getClass()
è vero.
Ora supponiamo
Teacher t = new Teacher();
senza generici è possibile il seguito.
Class studentClassRef = t.getClass();
Ma adesso è sbagliato ..?
es.) public void printStudentClassInfo(Class studentClassRef) {}
può essere chiamato conTeacher.class
Questo può essere evitato usando i generici.
Class<Student> studentClassRef = t.getClass(); //Compilation error.
Ora cos'è T ?? T è parametri di tipo (chiamati anche variabili di tipo); delimitato da parentesi angolari (<>), segue il nome della classe.
T è solo un simbolo, come un nome di variabile (può essere qualsiasi nome) dichiarato durante la scrittura del file di classe. Successivamente, T verrà sostituito con un
nome di classe valido durante l'inizializzazione ( HashMap<String> map = new HashMap<String>();
)
per esempio) class name<T1, T2, ..., Tn>
Quindi Class<T>
rappresenta un oggetto di classe di tipo di classe specifico ' T
'.
Supponi che i tuoi metodi di classe debbano funzionare con parametri di tipo sconosciuti come di seguito
/**
* Generic version of the Car class.
* @param <T> the type of the value
*/
public class Car<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Qui T può essere usato come String
tipo come CarName
O T può essere usato come Integer
tipo come modelNumber ,
O T può essere usato come Object
tipo come istanza valida dell'auto .
Ora qui sopra è il semplice POJO che può essere utilizzato in modo diverso in fase di esecuzione.
Collezioni ad es.) Elenco, Set, Hashmap sono i migliori esempi che funzioneranno con oggetti diversi secondo la dichiarazione di T, ma una volta che abbiamo dichiarato T come String
ad es.) HashMap<String> map = new HashMap<String>();
Quindi accetterà solo oggetti di istanza di String Class.
Metodi generici
I metodi generici sono metodi che introducono i propri parametri di tipo. Questo è simile alla dichiarazione di un tipo generico, ma l'ambito del parametro type è limitato al metodo in cui è dichiarato. Sono consentiti metodi generici statici e non statici, nonché costruttori di classi generiche.
La sintassi per un metodo generico include un parametro di tipo, parentesi angolari interne e appare prima del tipo restituito dal metodo. Per i metodi generici, la sezione dei parametri di tipo deve essere visualizzata prima del tipo restituito dal metodo.
class Util {
// Generic static method
public static <K, V, Z, Y> boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
class Pair<K, V> {
private K key;
private V value;
}
Ecco <K, V, Z, Y>
la dichiarazione dei tipi usati negli argomenti del metodo che dovrebbe essere prima del tipo restituito che è boolean
qui.
Nel seguito; la dichiarazione di tipo <T>
non è richiesta a livello di metodo, poiché è già dichiarata a livello di classe.
class MyClass<T> {
private T myMethod(T a){
return a;
}
}
Ma di seguito è sbagliato poiché i parametri di tipo a livello di classe K, V, Z e Y non possono essere utilizzati in un contesto statico (metodo statico qui).
class Util <K, V, Z, Y>{
// Generic static method
public static boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
ALTRI SCENARI VALIDI SONO
class MyClass<T> {
//Type declaration <T> already done at class level
private T myMethod(T a){
return a;
}
//<T> is overriding the T declared at Class level;
//So There is no ClassCastException though a is not the type of T declared at MyClass<T>.
private <T> T myMethod1(Object a){
return (T) a;
}
//Runtime ClassCastException will be thrown if a is not the type T (MyClass<T>).
private T myMethod1(Object a){
return (T) a;
}
// No ClassCastException
// MyClass<String> obj= new MyClass<String>();
// obj.myMethod2(Integer.valueOf("1"));
// Since type T is redefined at this method level.
private <T> T myMethod2(T a){
return a;
}
// No ClassCastException for the below
// MyClass<String> o= new MyClass<String>();
// o.myMethod3(Integer.valueOf("1").getClass())
// Since <T> is undefined within this method;
// And MyClass<T> don't have impact here
private <T> T myMethod3(Class a){
return (T) a;
}
// ClassCastException for o.myMethod3(Integer.valueOf("1").getClass())
// Should be o.myMethod3(String.valueOf("1").getClass())
private T myMethod3(Class a){
return (T) a;
}
// Class<T> a :: a is Class object of type T
//<T> is overriding of class level type declaration;
private <T> Class<T> myMethod4(Class<T> a){
return a;
}
}
E infine il metodo statico necessita sempre di una <T>
dichiarazione esplicita ; Non deriverà dal livello di classe Class<T>
. Ciò è dovuto al livello di classe T associato all'istanza.
Leggi anche Restrizioni su Generics
Caratteri jolly e sottotitoli
argomento tipo per un metodo generico