Java Generic with ArrayList <? extends A> add element

前端 未结 6 918
遇见更好的自我
遇见更好的自我 2020-12-03 20:51

I have classes A, B, C and D where B extends A, C extends A and

相关标签:
6条回答
  • 2020-12-03 21:07

    You could just declare:

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

    You can add any element of class A or any of its subclasses into such a list. It is just that when you get from that list, you will only be able to call methods available on A.

    Note that A is not limited to being a "full fledged" class: it can be an abstract class or even an interface.

    0 讨论(0)
  • 2020-12-03 21:08

    Look at this example and choose as per your requirement

    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 讨论(0)
  • 2020-12-03 21:11

    It is not possible to add elements in collection that uses ? extends.

    ArrayList<? extends A> means that this is an ArrayList of type (exactly one type) that extends A. So you can be sure, that when you call get method, you'll get something that is A. But you can't add something because you don't know what exactly the ArrayList contains.

    0 讨论(0)
  • 2020-12-03 21:18

    ArrayList<? extends A> means an ArrayList of some unknown type that extends A.
    That type might not be C, so you can't add a C to the ArrayList.

    In fact, since you don't know what the ArrayList is supposed to contain, you can't add anything to the ArrayList.

    If you want an ArrayList that can hold any class that inherits A, use a ArrayList<A>.

    0 讨论(0)
  • 2020-12-03 21:22

    You can create the array list of super class type. so you can do this.

    ArrayList<A> arrayList=new ArrayList<A>();
    
    0 讨论(0)
  • 2020-12-03 21:27

    Did I use the <? extends A> correctly?

    List<? extends A> list; means that the 'list' refers to an object implemented interface List, and the list can hold elements inherited from class A (including A). In other words the following statements are correct:

    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>();
    

    Java generics are a compile-time strong type checking. The compiler uses generics to make sure that your code doesn't add the wrong objects into a collection.

    You tried to add C in ArrayList<B>

    listB1.add(new C());
    

    If it were allowed the object ArrayList<B> would contain different object types (B,C).
    That is why the reference listB1 works in 'read-only' mode. Additionally you could take a look at this answer.

    how to resolve this?

    List<A> list = new ArrayList<A>();
    
    0 讨论(0)
提交回复
热议问题