Java 泛型与 ArrayList <?扩展 A> 添加元素
Posted
技术标签:
【中文标题】Java 泛型与 ArrayList <?扩展 A> 添加元素【英文标题】:Java Generic with ArrayList <? extends A> add element 【发布时间】:2012-12-27 16:30:54 【问题描述】:我有课程 A
、B
、C
和 D
其中 B
扩展 A
、C
扩展 A
和 D
扩展 A
。
我有以下ArrayList
s,每个都有一些元素:
ArrayList<B> b;
ArrayList<? extends A> mix = b;
我打算让变量mix
包含B
、C
或D
类型的元素。我尝试将C
类型的元素添加到mix
中,如下所示:
mix.add(anElementOfTypeC);
但 IDE 不允许我这样做,它说:
anElementOfTypeC 不能通过调用方法转换为 CAP#1 转换,其中 CAP#1 是一个新的类型变量: CAP#1 extends A from 捕获?扩展 A
我是否正确使用了<? extends A>
?我该如何解决这个问题?
【问题讨论】:
从您的代码提取中,mix
实际上是 ArrayList<B>
这里...
在你的研究过程中——如果你做了一些,你有没有通过这个 SO 问题——***.com/questions/1910892/… ?
【参考方案1】:
无法在使用? extends
的集合中添加元素。
ArrayList<? extends A>
表示这是一个扩展A
的类型(正好是一个 类型)的ArrayList
。所以你可以确定,当你调用 get
方法时,你会得到 is A. 但是你不能添加一些东西,因为你不知道 ArrayList
到底是什么包含。
【讨论】:
【参考方案2】:查看此示例并根据您的要求进行选择
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
【讨论】:
【参考方案3】:我是否正确使用了
<? 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 泛型是一种编译时强类型检查。 编译器使用泛型来确保您的代码不会将错误的对象添加到集合中。
您尝试在ArrayList<B>
中添加C
listB1.add(new C());
如果允许,对象ArrayList<B>
将包含不同的对象类型(B、C)。
这就是 reference listB1 在“只读”模式下工作的原因。此外,您可以查看this answer。
如何解决?
List<A> list = new ArrayList<A>();
【讨论】:
【参考方案4】:您可以创建超类类型的数组列表。所以你可以这样做。
ArrayList<A> arrayList=new ArrayList<A>();
【讨论】:
【参考方案5】:你可以声明:
ArrayList<A> mix = new ArrayList<A>();
您可以将 A 类或其任何子类的任何元素添加到这样的列表中。只是当您从该列表中获取时,您将只能调用 A
上可用的方法。
请注意,A
不限于作为“成熟”类:它可以是抽象类甚至是接口。
【讨论】:
【参考方案6】:ArrayList<? extends A>
表示扩展 A
的某种未知类型的 ArrayList。
该类型可能不是C
,因此您不能将C
添加到ArrayList。
事实上,由于您不知道 ArrayList 应该包含什么,因此您无法将 anything 添加到 ArrayList。
如果您想要一个可以容纳任何继承 A
的类的 ArrayList,请使用 ArrayList<A>
。
【讨论】:
不能添加任何东西有点太严格了。我们可以添加null
,也可以将list.get(0)
添加回列表。我知道我选的太多了。 ;)
然而你可以声明Class<? extends A> c = B.class
...泛型让我很头疼:/
@RohitJain:不,您不能将list.get(0)
添加回列表
@JBNizet:我知道你在说什么;但这不是评论的主题。那是List<T>
,不是List<? extends A>
,这是评论的主题。
@JBNizet:我知道代码的含义。我并不否认元素来自List<? extends A>
的事实。但是在您“添加list.get(0)
”的地方,它是List<T>
。这就是区别。以上是关于Java 泛型与 ArrayList <?扩展 A> 添加元素的主要内容,如果未能解决你的问题,请参考以下文章