7
votes

Pourquoi les génériques en Java? Comment il est différent de la surcharge?

Je veux coder une méthode unique ajouter () code> en Java, qui pourrait ajouter des entiers, des chaînes, etc. Les génériques m'aideront.

Je ne pouvais pas comprendre le but ultime des génériques. Je suis tellement confus. P>

génériques vs surcharge? P>

public Integer add(Integer i, Integer j){return i+j;}
public String add(String i, String j){return i+j;}
public <T> T add(T i, T j){return i+j;} //this gives me error.


2 commentaires

Lorsque vous faites INTEGER I + INTEGER J , vous n'ajoutez pas réellement entiers . Les entiers ne prennent pas en charge l'opérateur + . Ils obtiennent une boîte à rebord dans intens , non directement ajoutés sous forme integer objets. Vous ne pouvez pas ajouter d'objets génériques car les objets ne prennent pas en charge l'opérateur + . Strings est un cas particulier et prend en charge + .


La seule raison pour laquelle vous appelleriez vos deux exemples ajoutez est dû au fait qu'ils utilisent les opérateurs + , qui est en fait une similitude sans signification car elle fait des choses complètement différentes pour les chaînes et les entiers. Les méthodes de nom basées sur ce qu'ils font réellement du point de vue de l'appelant - c'est-à-dire la somme et concaténate dans ce cas serait de bons noms.


8 Réponses :


4
votes

Je veux coder une méthode unique Ajouter () en Java, qui pourrait ajouter des entiers, des chaînes, etc. Les génériques m'aideront.

non

Les génériques sont utilisés pour Sécurité surtout à la compilation.

Vous pouvez spécifier un seul type à ajouter à la collection

Liste lst;

acceptera la chaîne uniquement, aucune superclasse de la chaîne Aucune sous-classe [par exemple, si elle existe]


1 commentaires

acceptera la chaîne uniquement, pas de superclasse de la chaîne Aucune sous-classe - ce n'est pas vrai. Quelque chose comme void add42 (liste liste) {list.add (42);} est parfaitement valide.



5
votes

Generics pourrait em> l'aide, le problème ici est que le fonctionnement + code> est défini uniquement pour Java Primitives et String code> mais pas pour les types en général . Et en Java, nous ne pouvons pas surcharger aux opérateurs (comme nous pouvons faire en C ++ par exemple).

Une solution pratique sans génériques serait la suivante: p>

public Integer add(Integer a, Integer b) { return a + b; }    // sum of a and b
public String add(String a, String b) { return a + b; }      // concatenate operation!
public MyType add(MyType a, MyType b) { return a.add(b); }   // requires add operation


4 commentaires

Votre deuxième paragraphe n'est pas vrai. Le type de retour ne fait pas partie de la signature de méthode en Java, uniquement les types de noms et de paramètres. Tant que les paramètres sont distincts, vous pouvez avoir des types de rendement différents. Ou avez-je mal compris ce que vous avez écrit?


La surcharge n'a pas déterminé avec le type de retour. Il n'est pas nécessaire que le type de retour soit identique à la surcharge.


@Jonathan - merci beaucoup - c'était un shortonconefeError typique :-) a changé la réponse à un parcours "Java pour débutants";)


@Jonathan: Le type de retour fait partie de la signature, mais vous ne pouvez pas avoir deux méthodes qui ne diffèrent que dans le type de retour (car il est trop ambigu que vous appelez)



2
votes

Les génériques sont agréables car si cela vous a fait correctement, il vous permet de généraliser une partie du code que vous avez écrit. En termes d'écriture, vous souhaitez minimiser le code inutile et réutiliser autant de code que possible.

En utilisant l'approche de surcharge, vous devez écrire chacune des surcharges, avec des génériques que vous devez le faire une fois. Les génériques fonctionnent bien dans des situations où vous manipulez une collection depuis que vous effectuez certaines opérations communes sur un ensemble de collections. Dans certaines situations si vous désirez une approche plus personnalisée pour manipuler certaines situations, vous devrez peut-être surcharger les méthodes, mais je vous ferai un objectif d'écrire des génériques si vous pouvez l'utiliser dans plusieurs endroits.


2 commentaires

Je suis donc confondu avec des génériques Java avec des modèles C ++. Si des liens pour la comparaison de génériques et de modèles me sont plus utiles.


Stackoverflow.com/questions/36347/... peut vous aider à comprendre les similitudes et les différences entre ces deux.



1
votes

C'est exactement le point de générique. Vous ne souhaitez pas implémenter une méthode qui peut tout accepter. Franchement, vous pouvez toujours mettre en œuvre la méthode

ajouter (objet obj)

et transmettez-lui des entiers, des cordes, des booléens ... Mais dans la plupart des cas, vous ne voulez pas pour ça. La méthode doit faire face à l'argument et il devrait donc connaître le type du paramètre. C'est la raison pour laquelle si vous souhaitez faire une méthode, ajouter que les chaînes et les entiers impliquent 2 méthodes: xxx

maintenant, vous ne pouvez pas envoyer à Boolean à ajouter () méthode: une telle méthode juste n'existe pas.

Vous pouvez également implémenter la méthode générique

ajout (t arg);

et appelez Il: ceci. Ajouter ("Bonjour"); ou ceci. Ajouter (123); Code> Ceci. Ajouter (123); Cause Erreur de compilation.


0 commentaires

4
votes
public <T extends XXXXX> T add(T i, T j) { return i+j; }

1 commentaires

Merci d'avoir mentionné le étend , était sur le point de le faire moi-même.



1
votes

Que diriez-vous d'une approche avec une interface générique: xxx pré>

et une classe de gestionnaire: p> xxx pré>

maintenant Vous pouvez maintenant enregistrer et utiliser personnalisé Additionneurs pour différentes classes: P>

String addedString = manager.getAdder(String.class).add("abc", "def");

@SuppressWarnings("unchecked") // this is necessary because of
                               // the generic <Integer> type
List<Integer> addedList = manager
                            .getAdder(List.class)
                            .add(
                                Arrays.asList(1,2,3),
                                Arrays.asList(4,5,6)
                             );


0 commentaires

1
votes

Génériques en Java n'ajoute que la coulée au bytecode.

Le code sera le même, à l'exception de la coulée. P>

donc les deux constructions: p>

List list1 = new ArrayList();
List<String list2 = new ArrayList<String>();
....
String string1 = (String) list1.get(0);
String string2 = list2.get(0);


0 commentaires

5
votes

D'autres ont souligné pourquoi cela ne fonctionne pas. Permettez-moi d'ajouter simplement, je pense que vous êtes mal compris que les génériques Java sont pour. Peut-être êtes-vous familiarisé avec les modèles C ++, ou avec une expansion macro, qui ressemble tous deux des génériques, mais sont une chose très différente.

Les génériques sont vraiment sur la sécurité des types et évitant les moulages en désordre. Vous dites au compilateur qu'une certaine collection contient des chaînes, puis il sait que tout ce que vous mettez dans ou que vous sortez doit être une chaîne. Vous obtenez une vérification du temps compilé sur les choses que vous avez placées et vous économisez des moulages sur les choses que vous découlez.

Il ne provoque pas que le compilateur génère un code différent selon le type. Les génériques ne sont pas un moyen de courte main pour éviter de devoir écrire, dire, une version "int" et une version "flottante" de la même fonction, comme une macro ou un modèle C ++ feront pour vous. Vous pourrez peut-être obtenir un tel comportement distinct souhaité en disposant de deux classes qui implémentent la même fonction, mais une utilisation d'int et de l'autre en utilisant des flotteurs. Mais vous pouvez le faire avec des techniques orientées objet sans génériques. Si vous ne pouvez pas obtenir le comportement distinct souhaité à l'aide de techniques orientées objet "non génériques", vous ne pouvez pas le faire avec des génériques non plus.


0 commentaires