我有课程A
,B
,C
和D
其中B
延伸A
,C
延伸{{ 1}}和A
扩展D
。
我有以下A
个,其中包含一些元素:
ArrayList
我打算让变量ArrayList<B> b;
ArrayList<? extends A> mix = b;
包含mix
,B
或C
类型的元素。我尝试将D
类型的元素添加到C
中,如下所示:
mix
但IDE不允许我这样做,它说:
anElementOfTypeC无法通过调用方法转换为CAP#1 转换,其中CAP#1是一个新的类型变量:CAP#1从A扩展A. 捕获?延伸A
我是否正确使用了mix.add(anElementOfTypeC);
?我该如何解决这个问题?
答案 0 :(得分:36)
ArrayList<? extends A>
表示扩展A
的某种未知类型的ArrayList
该类型可能不是C
,因此您无法向ArrayList添加C
。
事实上,由于您不知道ArrayList应该包含什么,因此您无法将任何添加到ArrayList。
如果您想要一个可以容纳任何继承A
的类的ArrayList,请使用ArrayList<A>
。
答案 1 :(得分:7)
无法在使用? extends
的集合中添加元素。
ArrayList<? extends A>
表示这是ArrayList
类型(恰好一个类型),可以扩展A
。所以你可以肯定,当你打电话给get
方法时,你会得到 A的东西。但你不能添加东西,因为你不知道究竟是什么包含{ {1}}。
答案 2 :(得分:6)
我是否正确使用了
<? extends A>
?
List<? extends A> 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以'只读'模式工作的原因。此外,您可以查看this answer。
如何解决这个问题?
List<A> list = new ArrayList<A>();
答案 3 :(得分:3)
你可以宣布:
ArrayList<A> mix = new ArrayList<A>();
您可以将A类或其任何子类的任何元素添加到此类列表中。只有当您从该列表中获取时,您才能调用A
上可用的方法。
请注意,A
不仅限于“完全成熟”类:它可以是抽象类,甚至是接口。
答案 4 :(得分:0)
您可以创建超类类型的数组列表。所以你可以这样做。
ArrayList<A> arrayList=new ArrayList<A>();
答案 5 :(得分: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{
}