81 votes

java génériques mot-clé super

Je suis passé par ces sujets

Cependant, j'ai toujours semblent être un peu perdu avec super mot-clé:

  1. Lors de la déclaration d'une collection comme ça:

    List<? super Number> list = null;
    list.add(new Integer(0));//this compiles
    list.add(new Object());//this doesn't compile
    

    ne devrait-elle pas être l'opposé, nous avons une liste qui contient des objets de type inconnu) qui sont les parents de Number. Donc, Object doit s'adapter (puisqu'il est le parent de l' Number), et Integer ne le sont pas. Le contraire est le cas pour certaines raisons.

  2. Si nous avons le code suivant

    static void test(List<? super Number> param) {
        param.add(new Integer(2));
    }
    public static void main(String[] args) {
        ArrayList<String> sList = new ArrayList<String>();
        test(sList);            //will never compile, however...
    }
    

    Il est impossible de compiler le code ci-dessus (et de ma santé mentale suggère que c'est le bon comportement), mais la logique de base pourrait prouver le contraire:

    String is Object, Object is superclass of Number. So String should work.

    Je sais que c'est fou, mais n'est-ce pas la raison pour laquelle ils n'ont pas autoriser <S super T> constructions? Si oui, alors pourquoi <? super T> est-elle autorisée?

Quelqu'un pourrait-il m'aider à restaurer la partie manquante de cette logique de la chaîne?

104voto

polygenelubricants Points 136838

Le délimitée générique en List<? super Number> pouvez capturer Number et l'un de ses aux supertypes. Depuis Number extends Object implements Serializable, cela signifie que les seuls types qui sont actuellement capture-convertible en List<? super Number> sont:

  • List<Number>
  • List<Object>
  • List<Serializable>

Notez que vous pouvez add(Integer.valueOf(0)) à l'un des types ci-dessus. cependant, vous ne POUVEZ PAS add(new Object()) d'un List<Number> ou List<Serializable>, depuis que viole le type générique de la sécurité de la règle.

Par conséquent, il n'est PAS vrai que vous avez peut - add tout supertype de Number d'un List<? super Number>; ce n'est simplement pas comment délimitée générique de capture et de conversion de travail. Vous ne déclarez pas un List<? super Number> parce que vous voudrez peut-être ajouter un Object (vous ne pouvez pas!); vous le faites parce que vous voulez ajouter Number objets (c'est à dire que c'est un "consommateur" de Number), et simplement, List<Number> est trop restrictive.

Références

Voir aussi

  • Efficace Java 2nd Edition, Point 28: Utilisation délimitée des caractères génériques pour augmenter la flexibilité de l'API
    • "PECS stands pour le producteur-extends, de la consommation-super

Questions connexes

  • Trop nombreuses pour les énumérer, PECS, new Integer(0) vs valueOf, etc

25voto

Colin Hebert Points 40084

Pour la première partie, List<Number> correspond List<? super Number> mais vous ne pouvez pas ajouter un Object d'un List<Number>. C'est pourquoi vous ne pouvez pas ajouter un Object de List<? super Number>.

D'autre part, vous pouvez ajouter chaque sous-classe d' Number (Number inclus) à votre liste.

Pour la deuxième partie, String est Object, mais String n'est pas une super-classe de Number.

Si elle a travaillé comme ceci, comme chaque classe est une sous-classe de la Object, super n'aurait pas de sens.


Voyons tous les cas possibles avec List<? super Number> :


  • La liste est un List<Object>
    • List<Object> fonctionnera
    • Object correspond <? super Number>
    • Vous pouvez ajouter n'importe quel sous-type de l' Number d'un List<Object>
    • Même si vous pouvez également ajouter d' String dans la seule chose dont vous êtes sûr, c'est que vous pouvez ajouter n'importe quelle sous-classe de la Number.

  • La liste est un List<Number> :
    • List<Number> fonctionnera
    • Number correspond <? super Number>
    • Vous pouvez ajouter n'importe quel sous-type de l' Number d'un List<Number>

  • La liste est un List<Integer> (ou une sous-classe de Number):
    • List<Integer> ne fonctionne pas
    • Entier est une sous-classe de Number donc c'est exactement ce que nous voulons éviter
    • Même si un Integer correspond à un Number vous ne seriez pas en mesure d'ajouter une sous-classe de Number en List<Integer> (par exemple un Float)
    • super ne signifie pas une sous-classe.

  • La liste est un List<String> (ou de toute catégorie de ne pas étendre Number ni dans le "super" hiérarchie de l' Number (ie. Number et Object) :
    • List<String> ne fonctionne pas
    • String ne rentre pas dans Number "super hiérarchie"
    • Même si String correspond Object (qui est une super-classe de Number) vous woudln pas être sûr d'être en mesure d'ajouter un Number d'un List qui contiennent une sous-classe de l'un des super-classes de Number)
    • super ne signifie pas que toute sous-classe de l'un des super-classes, il signifie seulement l'un des super-classes.

Comment ça fonctionne ?

On pourrait dire que tant que vous pouvez ajouter n'importe quelle sous-classe de la Number avec votre tapé List, il respecte l' super mot-clé.

15voto

Tom Clift Points 1057

J'ai eu le même problème. Je pense que la syntaxe est la cause de la confusion.

List<? super Number> semble suggérer "une liste de choses qui sont aux supertypes de Nombre", mais ce que cela signifie réellement "une liste de choses qui ont comme Nombre de leurs supertype".

Une fois que j'ai commencé à le lire comme cela, il a cliqué.

6voto

AbstaubBaer Points 1

List<? super Number> signifie que le type de référence de la variable nous propose une liste de Nombres, des Objets ou des Serializables.

La raison pour laquelle vous ne pouvez pas ajouter un Objet, c'est parce que le Compilateur ne sait pas LEQUEL de ces classes sont dans le générique de la définition réelle de l'objet instancié, donc il vous permet de passer ou de Numéro de sous-types du Numéro, le Double, Entier et ainsi de suite.

Disons que nous avons une méthode qui retourne un List<? super Number>. La création de l'objet à l'intérieur de la méthode est encapsulé à partir de notre point de vue, nous ne pouvons pas dire si c'est quelque chose comme ceci:

List<? super Number> returnValue = new LinkedList<Object>();

ou

List<? super Number> returnValue = new ArrayList<Number>();

Donc, le type générique pourrait être l'Objet ou le Nombre. Dans les deux cas, nous serions autorisés à ajouter un Numéro, mais seulement dans un cas, il nous serait permis d'ajouter l'Objet.

Vous avez de distinguer entre le type de référence et l'objet réel dans ce type de situation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X