Génériques Java T vs Object

127

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 pu trouver cette question ailleurs sur ce site.

Abidi
la source

Réponses:

112

Isolé du contexte - aucune différence. Sur les deux tet objvous 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 cache cela)
  • compilez la sécurité du temps qui fonctionne. Si la Objectversion est utilisée, vous ne serez pas sûr que la méthode retourne toujours Foo. S'il revient Bar, vous aurez un ClassCastException, au moment de l'exécution.
Bozho
la source
14

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 (n'importe quelle classe, pas nécessairement du même type).

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

Example ex = new Example<Integer>();

Ici, nous spécifions quel type T sera ce qui nous permet d'appliquer plus de contraintes sur 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érerons une instance Integer ou Example.

L'objectif principal ici est que le code appelant puisse spécifier le type d'objets sur lesquels une classe fonctionnera, au lieu de s'appuyer sur la conversion de type pour appliquer cela.

Voir Java Generics * d'Oracle.

* Lien mis à jour.

Adam
la source
13

La différence est qu'avec les méthodes génériques, je n'ai pas besoin de lancer et j'obtiens une erreur de compilation lorsque je fais mal:

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;
    }
}

En utilisant un objet, j'ai toujours besoin de lancer et je n'obtiens aucune erreur lorsque je fais mal:

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;
    }
}
user1883212
la source
comme pour mentionner que vous n'avez plus à lancer d'objets non plus, à partir d'Android 6.
John Lord
2

Vous n'avez pas besoin de lancer de cours supplémentaires. Dans le premier cas, vous obtiendrez toujours un objet de classe java.lang.Object dont vous aurez besoin pour convertir 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.

Andrey Adamovich
la source
2

Au moment de 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 de) quel que soit le type T résolu (le premier exemple fait également la vérification de type mais chaque objet est un sous-type d'objet afin que chaque type soit accepté).

Jonathan
la source
2

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

String response = doSomething("hello world");

OU

MyObject response = doSomething(new MyObject());

OU

Integer response = doSomething(31);

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

Mais s'il est déclaré renvoyer Object, vous ne pouvez pas le faire à moins que vous n'ayez tapé cast things.

Adarshr
la source
Pouvons-nous dire qu'avec <T>il n'y a pas de boxe automatique?
SMUsamaShah
0

dans le premier cas, il prend un paramètre de n'importe quel type egstring et retourne un type foo. Dans le second cas, il prend un paramètre de type foo et retourne un objet de type foo.

fastcodejava
la source