Java génériques T vs object

Je me demandais quelle est la différence entre les deux déclarations de méthode suivantes:

public Object doSomething(Object obj) {....} public  T doSomething(T t) {....} 

Y a-t-il quelque chose que vous pouvez / pourriez faire avec l’un mais pas l’autre? Je n’ai pas trouvé cette question ailleurs sur ce site.

Isolé du contexte – pas de différence. Sur t et obj vous ne pouvez invoquer que les méthodes de Object .

Mais avec le contexte – si vous avez une classe générique:

 MyClass my = new MyClass(); Foo foo = new Foo(); 

Alors:

 Foo newFoo = my.doSomething(foo); 

Même code avec object

 Foo newFoo = (Foo) my.doSomething(foo); 

Deux avantages:

  • pas besoin de lancer (le compilateur te le cache)
  • comstackr le temps de sécurité qui fonctionne. Si la version Object est utilisée, vous ne serez pas sûr que la méthode retourne toujours Foo . S’il renvoie Bar , vous aurez une ClassCastException , à l’exécution.

La différence ici est que dans le premier, nous spécifions que l’appelant doit passer une instance Object (n’importe quelle classe), et il récupérera un autre Object (toute classe, pas nécessairement du même type).

Dans le second cas, le type renvoyé sera du même type que celui donné lors de la définition de la classe.

 Example ex = new Example(); 

Nous spécifions ici quel type T sera ce qui nous permet d’imposer plus de contraintes sur une classe ou une méthode. Par exemple, nous pouvons instancier une LinkedList ou LinkedList et nous soaps que lorsque nous appelons l’une de ces méthodes, nous récupérerons une instance Integer ou Example.

L’objective principal ici est que le code appelant puisse spécifier le type d’objects sur lequel une classe fonctionnera, au lieu de compter sur la conversion de type pour l’imposer.

Voir Java Generics * depuis Oracle.

* Lien mis à jour.

La différence est que, avec les méthodes génériques, je n’ai pas besoin de lancer et j’ai une erreur de compilation lorsque je me trompe:

 public class App { public static void main(Ssortingng[] args) { Ssortingng s = process("vv"); Ssortingng b = process(new Object()); // Compilation error } public static  T process(T val) { return val; } } 

En utilisant un object, j’ai toujours besoin de lancer et je ne reçois aucune erreur quand je fais mal:

 public class App { public static void main(Ssortingng[] args) { Ssortingng s = (Ssortingng)process("vv"); Ssortingng b = (Ssortingng)process(new Object()); } public static Object process(Object val) { return val; } } 

À l’exécution, rien. Mais au moment de la compilation, le second effectuera une vérification de type pour s’assurer que le type du paramètre et le type de la valeur de retour correspondent (ou sont des sous-types) à tout type de T (le premier exemple fait également la vérification de type sous-type d’object afin que chaque type soit accepté).

T est un type générique. Cela signifie qu’il peut être remplacé par n’importe quel object qualifiant à l’exécution. Vous pouvez invoquer une telle méthode comme suit:

Ssortingng response = doSomething("hello world");

OU

MyObject response = doSomething(new MyObject());

OU

Integer response = doSomething(31);

Comme vous pouvez le voir, il y a un polymorphism ici.

Mais s’il est déclaré pour retourner un object, vous ne pouvez pas le faire à moins de taper des éléments.

Vous n’avez pas besoin de faire un casting de classe supplémentaire. Dans le premier cas, vous obtiendrez toujours un object de classe java.lang.Object que vous devrez convertir dans votre classe. Dans le second cas, T sera remplacé par la classe définie dans la signature générique et aucune conversion de classe ne sera nécessaire.

dans le premier cas, il prend un paramètre de n’importe quel type egssortingng et renvoie un type foo. Dans le second cas, il prend un paramètre de type foo et renvoie un object de type foo.