web-dev-qa-db-fra.com

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> T doSomething(T t) {....}

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

109
Abidi

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<Foo> my = new MyClass<Foo>();
Foo foo = new Foo();

Ensuite:

Foo newFoo = my.doSomething(foo);

Même code avec objet

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

Deux avantages:

  • pas besoin de casting (le compilateur vous le cache)
  • compilez la sécurité de temps qui fonctionne. Si la version Object est utilisée, vous ne serez pas sûr que la méthode retourne toujours Foo. S'il retourne Bar, vous aurez un ClassCastException à l'exécution.
93
Bozho

La différence ici est que dans la première, nous spécifions que l'appelant doit passer une instance d'objet (n'importe quelle classe) et qu'il récupérera un autre objet (n'importe quelle classe, pas nécessairement du même type).

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

Example ex = new Example<Integer>();

Ici, nous spécifions quel type T sera ce qui nous permettra d’appliquer plus de contraintes à une classe ou à une méthode. Par exemple, nous pouvons instancier un LinkedList<Integer> ou LinkedList<Example> et nous savons que lorsque nous appelons l’une de ces méthodes, nous récupérons une instance Integer ou Example.

L'objectif principal ici est que le code appelant puisse spécifier le type d'objets sur lequel une classe va opérer, au lieu de s'appuyer sur le transtypage pour appliquer cela.

Voir Java Generics * d’Oracle.

* Lien mis à jour.

10
Adam

La différence est qu'avec les méthodes génériques, je n'ai pas besoin de transtyper et je reçois une erreur de compilation lorsque je me trompe:

public class App {

    public static void main(String[] args) {

        String s = process("vv");
        String b = process(new Object()); // Compilation error
    }

    public static <T> T process(T val) {

        return val;
    }
}

Utiliser un objet que j’ai toujours besoin de lancer et je n’obtiens aucune erreur lorsque je me trompe:

public class App {

    public static void main(String[] args) {

        String s = (String)process("vv");
        String b = (String)process(new Object());
    }

    public static Object process(Object val) {

        return val;
    }
}
7
user1883212

À l'exécution, rien. Mais au moment de la compilation, le second fera 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 de) quel que soit le type résolu par T (le premier exemple effectue également une vérification de type, mais chaque objet est un sous-type d’objet afin que chaque type soit accepté).

2
Jonathan

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

String response = doSomething("hello world");

OR

MyObject response = doSomething(new MyObject());

OR

Integer response = doSomething(31);

Comme vous pouvez le constater, il existe un polymorphisme ici.

Mais si il est déclaré de retourner Object, vous ne pouvez le faire que si vous tapez cast.

2
adarshr

Vous n'avez pas besoin de faire un casting de classe supplémentaire. Dans le premier cas, vous obtiendrez toujours un objet de la classe Java.lang.Object que vous devrez transtyper 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.

1
Andrey Adamovich

dans le premier cas, il prend un paramètre de type quelconque, par exemple une chaîne, et renvoie un type foo. Dans le second cas, il prend un paramètre de type foo et retourne un objet de type foo.

0
fastcodejava