首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带问号的泛型列表类型

带问号的泛型列表类型
EN

Stack Overflow用户
提问于 2018-06-28 16:37:08
回答 5查看 1.4K关注 0票数 8

我在解释/理解Java列表的泛型类型时遇到了问题:

代码语言:javascript
运行
复制
List<? extends Command> myVar = client.performAction(actionParams);

泛型类型? extends Command是如何调用的,比如它有名字吗?这种类型到底是什么?它是一个Command对象吗?或者这是否意味着它只接受扩展Command的类?我使用这种构造的优势是什么?在哪个Java版本中集成了这种类型的构造?

EN

回答 5

Stack Overflow用户

发布于 2018-06-28 16:41:32

通配符用于放宽您可以使用的对象的类型限制。在本例中,您接受extends/implements Command类型的所有内容。

票数 8
EN

Stack Overflow用户

发布于 2018-06-28 17:00:51

关于List<? extends Command>的重要一点是它是一种抽象类型。您不能编写new List<? extends Command>()并期望创建某些内容。有两个原因。

  • List是一个接口,具有ArrayListLinkedList等具体实现。
  • 类型参数中的通配符,这意味着“这可以是Command的子类型的任何类型,包括Command本身”。

这意味着List<? extends Command>类型的变量可以引用这些具体类型中的任何一个对象

  • ArrayList<Command>
  • LinkedList<SpecialCommand>
  • CopyOnWriteArrayList<ImportantCommand>

还有许多其他的组合。当然,假设SpecialCommandImportantCommandCommand的子类型。

当您创建该变量将要引用的对象时,您需要明确说明它是什么具体类型。例如

代码语言:javascript
运行
复制
List<? extends Command> myCommandList = new ArrayList<SpecialCommand>();

完成此操作后,当然可以在myCommandList上调用一些常用的List方法,例如

代码语言:javascript
运行
复制
Command firstCommand = myCommandList.get(0);

这很好,因为我们知道无论列表中的对象是什么,它们都是某种类型的Command。但你不能像这样做

代码语言:javascript
运行
复制
SpecialCommand mySpecialCommand = new SpecialCommand();
myCommandList.add(mySpecialCommand);

因为编译器无法知道您是否将正确类型的对象添加到列表中。在这一点上,myCommandList同样可以是LinkedList<ImportantCommand>或类似的,编译器需要防止向其添加SpecialCommand

这意味着您应该仅在以下情况下使用List<? extends Command>类型

  • 你不关心它是什么类型的列表(ArrayListLinkedList或whatever)
  • you不关心列表中的Command是什么类型,你不会想要向列表中添加任何东西。

这意味着您通常不会将其用于局部变量或字段。它更有可能是一个方法参数,其中传入的内容可能是LinkedList<ImportantCommand>或其他什么;但是您在该方法中要做的就是从列表中取出对象,并对它们执行Command类型操作。

从Java5开始,Java中就包含了泛型,包括通配符。

票数 3
EN

Stack Overflow用户

发布于 2018-06-28 16:47:08

泛型类型? extends Command是怎么叫的,比如它有名字吗?

这些被称为通用wildcards

这个类型到底是什么?它是一个Command对象吗?

它只用于在编译时检查变量赋值。在运行时,泛型是erased的,并解释为List myVar = client.performAction(actionParams);

这是否意味着它只接受扩展Command的类?

您只能指定List<Command> myVar = client.performAction(actionParams);,它将接受任何Command类型的对象或command的子类。

List<? extends Command> myVar控制变量赋值。因此,您只能将以下泛型分配给myVar。假设SubCommand扩展了命令,则以下赋值均有效:

代码语言:javascript
运行
复制
myVar = new ArrayList<SubCommand>
myVar = new ArrayList<Command>

当使用通配符泛型声明集合时,它也可以变成read-only。例如,myVar.add(new SubCommand());将导致编译器错误。

我使用这种构造的优势是什么?

最初,Java不包含泛型。它是在Java5.0中添加的,以允许Java集合的类型限制,如ListSetMap等。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51078308

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档