带有问号的通用列表类型

时间:2018-06-28 08:37:08

标签: java

我在解释/理解Java列表的通用类型时遇到困难:

List<? extends Command> myVar = client.performAction(actionParams);

如何调用通用类型? extends Command,就像它的名称一样?这到底是什么类型?它是Command对象吗?还是这意味着它仅接受扩展Command的类?使用这种结构的优势是什么?这种结构在什么Java版本中集成?

5 个答案:

答案 0 :(得分:7)

Upper-bounded通配符用于放宽可以使用的对象的类型限制。在这种情况下,您接受扩展/实现 Command类型的所有内容。

答案 1 :(得分:2)

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

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

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

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

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

在创建该变量将要引用的对象时,需要明确说明其具体类型。例如

List<? extends Command> myCommandList = new ArrayList<SpecialCommand>();

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

Command firstCommand = myCommandList.get(0);

这很好,因为我们知道列表中的任何对象,它们都将是某种类型的Command。但是你不能做类似的事情

SpecialCommand mySpecialCommand = new SpecialCommand();
myCommandList.add(mySpecialCommand);

因为编译器无法知道您正在向列表中添加正确的对象。此时,myCommandList可以是LinkedList<ImportantCommand>或类似名称,并且编译器需要阻止向其添加SpecialCommand

这意味着,只有在其中有变量where时,才应使用类型List<? extends Command>

  • 您不在乎列表是哪种类型(ArrayListLinkedList等)
  • 您不在乎列表中是哪种Command
  • 您不会尝试将任何内容添加到列表中。

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

自Java 5以来,泛型就一直使用Java,包括通配符。

答案 2 :(得分:1)

  

如何调用通用类型? extends Command,例如   的名字吗?

这些被称为通用wildcards

  

此类型究竟是什么?它是Command对象吗?

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

  

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

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

List<? extends Command> myVar控制变量分配。因此,您只能将以下泛型分配给myVar。假设SubCommand扩展了Command,以下分配都是有效的:

myVar = new ArrayList<SubCommand>
myVar = new ArrayList<Command>

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

  

使用这种结构对我有什么好处?

最初,Java不包含泛型。它是在Java 5.0中添加的,以允许对Java集合进行类型限制,例如ListSetMap等。

答案 3 :(得分:1)

既然您一次问了很多问题,让我简要介绍一下:

  • 当您实现要在不同对象上使用的数据结构,容器或算法而不必重写整个代码时,泛型至关重要。
  • 如果我没有记错 Java 5.0 中引入的泛型, 在使用Java泛型之前,您仍然可以创建包含Object对象的灵活数据结构,但是必须cast转换为最终类型并在代码中的很多地方使用instanceOf。因此引入了泛型以缓解此问题并简化代码。
  • NiVeR已经说过,?是通配符,List<? extends Command>将限制List包含扩展或实现< / strong>类或接口Command 强制对对象接口施加约束

答案 4 :(得分:1)

List<? extends Command>被称为上限通配符(许多答案已经解决了此问题)。通常,没有人会这样宣布自己的名单;主要用于方法(更常见的是静态方法)。

List<? extends Command>是指包含{em>一种特定类型的{em> {em}(即一个特定的子类)的列表。由于它是未知的子类类型,因此在编译时,您将无法添加任何内容。您的IDE可能会将Command方法解析为add

add(null e)尽管看似相似,但它指的是可以容纳任何内容的列表,只要它是List<Command>(或从Command继承而来)即可。

示例:

Command

使用时间示例:

List<? extends Command> commands = new ArrayList<FooCommand>();
commands.add(new FooCommand()); // Not allowed at compile time

List<Command> commands = new ArrayList<>();
commands.add(new FooCommand());
commands.add(new BarCommand());