Lo spiego in modo semplice.
I generici definiti a livello di classe sono completamente separati dai generici definiti a livello di metodo (statico).
class Greet<T> {
public static <T> void sayHello(T obj) {
System.out.println("Hello " + obj);
}
}
Quando vedi il codice sopra riportato ovunque, tieni presente che la T definita a livello di classe non ha nulla a che fare con la T definita nel metodo statico. Anche il seguente codice è completamente valido ed equivalente al codice sopra.
class Greet<T> {
public static <E> void sayHello(E obj) {
System.out.println("Hello " + obj);
}
}
Perché il metodo statico deve avere i propri generici separati da quelli della classe?
Questo perché, il metodo statico può essere chiamato senza nemmeno creare un'istanza della classe. Quindi, se la Classe non è ancora istanziata, non sappiamo ancora cosa sia T. Questo è il motivo per cui i metodi statici devono avere i propri generici.
Quindi, ogni volta che chiami il metodo statico,
Greet.sayHello("Bob");
Greet.sayHello(123);
JVM lo interpreta come segue.
Greet.<String>sayHello("Bob");
Greet.<Integer>sayHello(123);
Entrambi danno gli stessi risultati.
Hello Bob
Hello 123