33

我有类A,B和where extends , extendsC和extends 。DBACADA

我有以下ArrayList每一个都包含一些元素:

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

我打算让变量mix包含或类型B的元素。我试图像这样添加一个类型的元素:CDCmix

mix.add(anElementOfTypeC);

但是 IDE 不允许我这样做,它说:

anElementOfTypeC 不能通过调用转换方法转换为 CAP#1,其中 CAP#1 是一个新的类型变量:CAP#1 从捕获的 ? 扩展 A 扩展 A

我用对了<? extends A>吗?我该如何解决这个问题?

4

6 回答 6

44

ArrayList<? extends A>表示某种未知类型的 ArrayList 扩展A
该类型可能不是C,因此您不能将 a 添加C到 ArrayList。

事实上,由于您不知道 ArrayList 应该包含什么,因此您无法向 ArrayList 添加任何内容

如果您想要一个可以包含任何继承类的 ArrayList A,请使用ArrayList<A>.

于 2013-01-13T17:35:01.887 回答
12

无法在使用的集合中添加元素? extends

ArrayList<? extends A>意味着这是一个扩展ArrayList的类型(恰好是一种A类型) 。所以你可以肯定,当你调用get方法时,你会得到一个A。但是你不能添加一些东西,因为你不知道究竟ArrayList包含什么。

于 2013-01-13T17:34:38.780 回答
7

我用对了<? extends A>吗?

List<? extends A> list;表示'list'指的是一个对象实现的接口List,并且该list可以保存从类A(包括A)继承的元素。换句话说,以下陈述是正确的:

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 泛型是一种编译时强类型检查。编译器使用泛型来确保您的代码不会将错误的对象添加到集合中。

您尝试C添加ArrayList<B>

listB1.add(new C());

如果允许,该对象ArrayList<B>将包含不同的对象类型(B,C)。
这就是为什么引用listB1 在“只读”模式下工作的原因。另外你可以看看这个答案

如何解决这个问题?

List<A> list = new ArrayList<A>();
于 2013-12-15T00:08:12.713 回答
3

你可以声明:

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

您可以将 A 类或其任何子类的任何元素添加到此类列表中。只是当您从该列表中获取时,您将只能调用可用的方法A

请注意,A它不仅限于成为“成熟”类:它可以是抽象类甚至是接口。

于 2013-01-13T17:34:41.677 回答
0

您可以创建超类类型的数组列表。所以你可以这样做。

ArrayList<A> arrayList=new ArrayList<A>();
于 2013-01-13T17:44:58.717 回答
0

查看此示例并根据您的要求进行选择

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{

}
于 2014-05-20T12:20:07.183 回答