web-dev-qa-db-fra.com

Générique Java avec ArrayList <? étend A> ajouter un élément

J'ai les classes A, B, C et DB s'étend A, Cétend A et Détend A.

J'ai la ArrayLists suivante avec chacun quelques éléments:

ArrayList<B> b;
ArrayList<? extends A> mix = b;

Je voulais que la variable mix contienne des éléments de type B, C ou D. J'ai essayé d'ajouter un élément de type C dans mix comme ceci:

mix.add(anElementOfTypeC);

Mais le IDE ne me permet pas de le faire et dit:

anElementOfTypeC ne peut pas être converti en CAP n ° 1 par la méthode d’invocation conversion où CAP # 1 est une nouvelle variable type: CAP # 1 étend A à partir de capture de? étend A

Ai-je utilisé le <? extends A> correctement? Comment puis-je résoudre ça?

24
vda8888

ArrayList<? extends A> désigne une ArrayList d'un type inconnu qui étend A.
Ce type peut ne pas être C, vous ne pouvez donc pas ajouter C à ArrayList.

En fait, puisque vous ne savez pas ce que ArrayList est censé contenir, vous ne pouvez pas ajouter rien à ArrayList.

Si vous voulez une ArrayList pouvant contenir n'importe quelle classe qui hérite de A, utilisez un ArrayList<A>.

36
SLaks

Il n'est pas possible d'ajouter des éléments dans la collection qui utilisent ? extends.

ArrayList<? extends A> signifie qu'il s'agit d'une ArrayList de type ( exactement un type) qui étend A. Vous pouvez donc être sûr que lorsque vous appelez la méthode get, vous obtiendrez quelque chose qui est A. Mais vous ne pouvez pas ajouter quelque chose car vous ne savez pas exactement ce qui contient ArrayList.

7
Dmitry Zaytsev

Ai-je utilisé le <? extends A> correctement?

List<? extends A> list; signifie que la «liste» fait référence à une liste d'interface implémentée par un objet et que la liste peut contenir des éléments hérités de la classe A (y compris A). En d'autres termes, les affirmations suivantes sont correctes:

List<? extends A> listA1 = new ArrayList<A>();
List<? extends A> listB1 = new ArrayList<B>();
List<? extends A> listC1 = new ArrayList<C>();
List<? extends A> listD1 = new ArrayList<D>();

Les génériques Java sont une vérification de type forte au moment de la compilation . Le compilateur utilise des génériques pour s’assurer que votre code n’ajoute pas les mauvais objets à une collection.

Vous avez essayé d'ajouter C dans ArrayList<B>

listB1.add(new C());

S'il était autorisé, l'objet ArrayList<B> contiendrait différents types d'objet (B, C).
C'est pourquoi la liste reference listB1 fonctionne en mode "lecture seule". De plus, vous pouvez regarder cette réponse

comment résoudre cela?

List<A> list = new ArrayList<A>();
6
Oleksandr

Vous pouvez simplement déclarer:

ArrayList<A> mix = new ArrayList<A>();

Vous pouvez ajouter n'importe quel élément de la classe A ou l'une de ses sous-classes dans une telle liste. C'est juste que lorsque vous obtenez de cette liste, vous ne pourrez appeler que des méthodes disponibles sur A.

Notez que A ne se limite pas à être une classe "à part entière": il peut s'agir d'une classe abstraite ou même d'une interface.

3
fge

Vous pouvez créer la liste de tableaux du type super classe. afin que vous puissiez le faire.

ArrayList<A> arrayList=new ArrayList<A>();
0
sumit sharma

Regardez cet exemple et choisissez selon vos besoins

package com.generic;

import Java.util.ArrayList;

public class SuperExtendTest {

    /**
     * @param args
     */
    public static void main(String[] args) {

    }
    public void test() throws Exception {
        ArrayList<Parent> parents=new ArrayList<>();
        parents.add(new Parent());
        parents.add(new Child());
        //parents.add(new GrandParent()); Not allowed

        ArrayList<Parent> p=new ArrayList<>();
        ArrayList<Child> c=new ArrayList<>();
        ArrayList<GrandParent> gp=new ArrayList<>();

        testExtendP(p);
        //testExtendP(c); Not allowed only super type allowed no child
        testExtendP(gp);

        testExtends(c);
        testExtends(p);
        //testExtends(gp); Not allowed because GrantParent does not extends Parent
    }

    /**
     * This Method allowed get operations for Parent 
     * No add 
     * 
     */
    public void testExtends(ArrayList<? extends Parent> list) throws Exception {
    /*  list.add(new Child());
        list.add(new Parent());
        list.add(new GrandParent());
        // can not add
        */
        Child c=(Child) list.get(0);
        Parent parent=list.get(0);
        GrandParent gp=list.get(0);
        /**
         * Unsafe collection way
         */
        ArrayList list2=new ArrayList();
        list.addAll(list2);
    }

    /**
     * This Method allowed add operations for Parent and it's sub types and on get it gives Object type 
     * 
     */
    public void testExtendP(ArrayList<? super Parent> list) throws Exception {
        list.add(new Child());
        list.add(new Parent());
        //list.add(new GrandParent());
        /*can not add because GrandParent can not be converted to Parent type
         * 
         * The method add(capture#3-of ? super Parent) in the type ArrayList<capture#3-of ? super Parent> is not applicable for the arguments (GrandParent)
         * 
         */

        Child c=(Child) list.get(0);
        Parent parent=(Parent) list.get(0);
        GrandParent gp=(GrandParent) list.get(0);
        Object obj=list.get(0);

        /**
         * Unsafe collection way
         */
        ArrayList list2=new ArrayList();
        list.addAll(list2);
    }

    /**
     * This Method allowed all operations for Parent and it's sub types 
     * 
     */
    public void testDirect(ArrayList<Parent> list) throws Exception {
        list.add(new Child());
        list.add(new Parent());
        //list.add(new GrandParent()); 
        /*
         * Can not add GrandParent (Normal generic rule)
         */
    }

}
class GrandParent{

}

class Parent extends GrandParent{

}
class Child extends Parent{

}
0
Ankit Katiyar