Meilleures pratiques Java-Renvoyer un objet par rapport à un générique


J'utilise des génériques pour la première fois pour un projet scolaire et j'ai rencontré un dilemme philosophique concernant le retour d'objets ou de mon élément générique déclaré dans mes méthodes.

Mon TOC me dit que je dois toujours renvoyer le type connu mais je trouve que cela crée des désagréments en aval lorsque je nourris des types de données primitifs dans ma classe (et, bien sûr, pour ce projet, je ne nourris que des primitives dans cette classe).

Voici un exemple de ce que je veux dire:

public class DansPriorityQueue<E extends Comparable> 
{
    private ArrayList<E> tree;

//Here's a method that returns an object
public Object peek() {
    return tree.get(0);
}

//Here's a method that returns the generic type
public E peek() {
    return tree.get(0);
}

(Comme un FYI.. Je suis obligé d'implémenter cette classe JDK moi-même mais je suis heureusement pas obligé d'implémenter les mêmes interfaces que la vraie PriorityQueue donc j'ai le choix si je veux utiliser l'objet ou le générique)

Mon problème

Cela me fait me sentir un peu sale mais je suis tenté juste de retourner un objet plutôt que mon élément générique E sur ces méthodes car quand je retourne E, JUnit me force à lancer mes valeurs entières:

DansPriorityQueue<Integer> dpq = new DansPriorityQueue<Integer>();
dpq.add(1);
assertEquals("Expected different value", (Integer) 1, dpq.peek());

Lorsque je renvoie un objet en revanche, l'auto-boxe ne me force pas à lancer ma valeur primitive.

Voici une description plus éloquente du problème auquel j'ai été confronté:

Http://www.aschroder.com/2009/10/php-1-java-0-the-method-assertequalsobject-object-is-ambiguous-for-the-type/

------------MODIFIER----------------

Voici l'erreur réelle que je reçois lorsque je renvoie le type générique et que je remplis ma liste avec l'objet entier autoboxé sans le cast ci-dessus: La méthode assertEquals (String, Object, Object) est ambiguë pour le type DansPriorityQueueTest

--------- FIN EDIT--------------

Questions

  1. Quelqu'un peut-il me dire pourquoi je devrais ou ne devrais pas retourner un objet par opposition à l'élément générique avec lequel je travaille? Les deux semblent avoir des avantages et des inconvénients... quelle est la meilleure pratique?

  2. Je sais vaguement que renvoyer un objet peut causer des problèmes de casting plus tard, mais je ne les ai pas encore rencontrés... quelqu'un a-t-il un exemple spécifique de la façon dont cela peut être dangereux?

  3. Dans le JDK, j'ai remarqué que de nombreuses méthodes de collections renvoient un objet par défaut. Est-ce parce que Generics a été introduit dans une version ultérieure de Java ou était-ce une décision consciente de Sun Systems?

Author: DanK, 2013-11-08

1 answers

Quelqu'un peut-il me dire pourquoi je devrais ou ne devrais pas retourner un objet par opposition à l'élément générique avec lequel je travaille? Les deux semblent avoir des avantages et des inconvénients... quelle est la meilleure pratique?

Cela dépend. Dans un cas comme celui - ci, vous voudriez un type générique-sinon, quel est l'intérêt de définir un type générique pour la classe?

Je sais vaguement que le retour d'un objet peut causer des problèmes de casting plus tard, mais je ne les ai pas encore rencontrés... quelqu'un aurait-il une exemple spécifique de la façon dont cela peut être dangereux?

Bien sûr!

DansPriorityQueue<String> queue = new DansPriorityQueue<String>();
//add items
Float f = (Float)queue.getObject();  //uh-oh! this compiles but will fail 
Float f = queue.getObject(); //generic type, fails during compile

Dans le JDK, j'ai remarqué que de nombreuses méthodes de collections renvoient un objet par défaut. Est-ce parce que Generics a été introduit dans une version ultérieure de Java ou était-ce une décision consciente de Sun Systems?

C'est principalement dû à la rétrocompatibilité, ou pour les cas où vous utiliserez vraiment la collection pour contenir des valeurs disparates (un méli-mélo de disons, JLabels, Chaînes et icônes pour exemple pour le rendu d'une JTable par exemple).

AssertEquals("Taille différente attendue", (Entier) 2, dpq.taille ());

Je ne pense pas que cela devrait être un problème. dpq.size () doit simplement renvoyer un int indépendamment de ce qui est stocké dans la file d'attente prioritaire. Ce ne serait pas une valeur générique.

, Vous pouvez créer quelque chose comme

DansPriorityQueue<Double> queue = new DansPriorityQueue<Double>();
for(double d = 0; d < 10; d+=1.0)
    queue.add(d);

Et cela ne devrait causer aucun problème, non?

 8
Author: Markus Koivisto, 2013-11-08 16:16:00