栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

将泛型列表分配给具体的ArrayList会导致编译时错误

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

将泛型列表分配给具体的ArrayList会导致编译时错误

今天早些时候,我认为您想

List<? extends AbstractInst<? extendsIInstType>>
成为的数据类型
insts
。当然,这是将与您创建的对象匹配的数据类型,但是我怀疑在这种情况下它是否真的是您想要的。请按要求进行解释。

假设您有一个扩展了另一个类的类,例如

PrintWriter
extends
Writer
。就是说,每个
PrintWriter
也都是a
Writer
,但是还有一些额外的方法(例如
println
),您可以使用type变量来调用
PrintWriter
,但不能使用type变量来调用
Writer
。(与标准相比,我更喜欢真实的示例
Dogextends Animal
)。

重要的是要了解它

ArrayList<PrintWriter>
不是的子类型
ArrayList<Writer>
,尽管从直观上看可能不是。原因是这样的。假设我有一个变量
myList
,并且写了
myList.add(newStringWriter());
什么类型的
myList
?显然不能是类型
ArrayList<PrintWriter>
,因为a
StringWriter
不是a
PrintWriter
。但是它 可能 是类型
ArrayList<Writer>
,因为a
StringWriter
肯定是a
Writer
,因此必须能够将其添加到中
ArrayList<Writer>


因此,任何

ArrayList<Writer>
行都可以正常工作

myList.add(new StringWriter());

但任何

ArrayList<PrintWriter>
不会 。因此,从某种意义上来说,a
ArrayList<PrintWriter>
不可能是的特殊类型。
ArrayList<Writer>``PrintWriter``Writer

换句话说,应该可以这样写

ArrayList<Writer> myList = new ArrayList<Writer>();myList.add(new StringWriter());

但是编译器应该以某种方式阻止我们编写此代码

ArrayList<Writer> myList = new ArrayList<PrintWriter>();myList.add(new StringWriter());

由于第二行显然可以,因此它必须是第一行会产生编译错误。事实上,这是-
你不能分配

ArrayList<PrintWriter>
给类型的变量
ArrayList<Writer>
,因为
ArrayList<PrintWriter>
只是
不是 一个
ArrayList<Writer>
。或如乔恩·斯基特(Jon
Skeet)在https://stackoverflow.com/a/2745301/1081110上所说的“Awooga awooga”。

尽管如此

ArrayList<Writer>
ArrayList<PrintWriter>
ArrayList<StringWriter>
似乎都有些相似。似乎应该有某种类型的变量可以引用这三个变量中的任何一个。确实有-是
ArrayList<?extends Writer>
。但这是一种 抽象类型 。您无法实例化它。您不能写
new ArrayList<? extendsWriter>()
-最终
ArrayList<? extendsWriter>
必须实际上是一个
ArrayList<Writer>
,一个
ArrayList<PrintWriter>
或一个
ArrayList<StringWriter>
(或可能是
ArrayList
某种其他类型的
Writer
)。

这对我们来说应该不会太打扰。毕竟

List<Writer>
也是抽象类型。您无法编写文字
new List<Writer>()
,因为a
List<Writer>
实际上必须是
ArrayList<Writer>
linkedList<Writer>
或其他类型的列表
Writer

另外,类型变量

ArrayList<? extendsWriter>
并不总是拥有最有用的变量,因为您不能使用它来向列表中添加内容。如果
myList
是类型的
ArrayList<? extendsWriter>
,那么你就不能写
myList.add(myWriter);
不论类型是什么
myWriter
是,因为编译器无法检查的方式
myWriter

正确 的排序
Writer
的名单。

您可以使用类型变量

ArrayList<? extends Writer>
来将事情从列表中删除。如果
myList
是类型
ArrayList<?extends Writer>
,则 可以

Writer myWriter = myList.get(0);

因为无论

myList
指的是
ArrayList<Writer>
an
ArrayList<PrintWriter>
还是an
ArrayList<StringWriter>
,您都知道其中的含义是
Writer

所以回到实际问题,你在哪里

List<AbstractInst<? extends IInstType>> insts = new ArrayList<MIPSInst>();

最初看来是合理的,因为正如您所解释的

MIPSInst
,的确是的子类型
AbstractInst<? extendsIInstType>
。或者换一种说法,每个
MIPSInst
都是一个
AbstractInst<? extends IInstType>

显然,您可能已经写过

List<MIPSInst> insts = new ArrayList<MIPSInst>();

并能够将内容添加到列表中,并从列表中删除内容。但是您想使用某种类型表达式来表明任何类型

AbstractInst<? extendsIInstType>
都可以,并且您只会将该变量用于可以在任何类型
List
AbstractInst<? extendsIInstType>
对象上使用的东西。

正如我在示例中展示

StringWriter / PrintWriter
的那样,您正在寻找的类型是
List<? extendsAbstractInst<? extends IInstType>>
。这封装了以下事实:该列表可以是
List
任何类型的
AbstractInst<?extends IInstType>
,包括
MIPSInst

但是,除非您将此变量强制转换为其他变量,否则使用此类型将限制您使用列表的只读视图。您可以

get
从列表中进行操作,但是却
add
一无所获,因为编译器无法检查添加的类型是否正确
AbstractInst<?extends IInstType>

在这种情况下,您将创建一个空列表。因此,引用可以让您

get
填充但不能
add
填充的引用可能不是很有用。因此,与我之前的评论相反,最好只是将变量声明为a
List<MIPSInst>
,然后将所有
add
事情都
get
放在心上。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/569506.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号