关于List<? extends Command> 的重要一点是它是一个抽象 类型。你不能写new List<? extends Command>() 并期望创造一些东西。有两个原因。
-
List 是一个接口,具体实现如ArrayList、LinkedList 等。
- type 参数中的通配符,意思是“这可以是
Command 的子类型,包括Command 本身”。
这意味着List<? extends Command> 类型的变量可以引用任何这些具体类型的对象
ArrayList<Command>
LinkedList<SpecialCommand>
CopyOnWriteArrayList<ImportantCommand>
和许多其他组合。当然假设SpecialCommand 和ImportantCommand 是Command 的子类型。
当您创建该变量将要引用的对象时,您需要明确说明它是什么具体类型。例如
List<? extends Command> myCommandList = new ArrayList<SpecialCommand>();
一旦你这样做了,当然,你可以在myCommandList上调用一些常用的List方法,比如
Command firstCommand = myCommandList.get(0);
这很好,因为我们知道列表中的任何对象都是Command 的某种类型。但你不能这样做
SpecialCommand mySpecialCommand = new SpecialCommand();
myCommandList.add(mySpecialCommand);
因为编译器无法知道您将正确类型的对象添加到列表中。此时,myCommandList 可能同样是 LinkedList<ImportantCommand> 或类似的,编译器需要阻止向其添加 SpecialCommand。
这意味着你应该只使用类型List<? extends Command>,如果你有一个变量在哪里
- 你不在乎它是什么样的列表(
ArrayList、LinkedList 或其他)
- 你不在乎列表中的
Command是什么类型
- 您不会尝试向列表中添加任何内容。
这意味着您通常不会将它用于局部变量或字段。它更有可能是一个方法参数,其中传入的东西可能是LinkedList<ImportantCommand> 或其他任何东西;但您在该方法中所做的只是将对象从列表中取出,并对它们执行Command 类型操作。
自 Java 5 以来,Java 中就有泛型,包括通配符。