# 泛型和子类型

> 原文： [https://docs.oracle.com/javase/tutorial/extra/generics/subtype.html](https://docs.oracle.com/javase/tutorial/extra/generics/subtype.html)

让我们测试一下你对泛型的理解。以下代码段是否合法？

```
List<String> ls = new ArrayList<String>(); // 1
List<Object> lo = ls; // 2 

```

第 1 行肯定是合法的。问题的棘手部分是第 2 行。这归结为这样的问题：`String`的`List`是`Object`的`List`。大多数人本能地回答：“当然！”

那么，看看接下来的几行：

```
lo.add(new Object()); // 3
String s = ls.get(0); // 4: Attempts to assign an Object to a String!

```

这里我们别名`ls`和`lo`。通过别名`lo`访问`ls`列表`String`，我们可以在其中插入任意对象。结果`ls`不再仅仅持有`String`，当我们尝试从中获取某些东西时，我们得到了一个粗鲁的惊喜。

Java 编译器当然会阻止这种情况发生。第 2 行将导致编译时错误。

通常，如果`Foo`是`Bar`的子类型（子类或子接口），并且`G`是一些泛型类型声明，则**而不是**的情况下`G&lt;Foo&gt;`是[的子类型] COD4]。这可能是您需要了解仿制药最困难的事情，因为它违背了我们深刻的直觉。

我们不应该假设收藏品不会改变。我们的直觉可能会让我们认为这些事情是不可改变的。

例如，如果汽车部门向人口普查局提供司机清单，这似乎是合理的。我们认为`List&lt;Driver&gt;`是`List&lt;Person&gt;`，假设`Driver`是`Person`的子类型。事实上，正在传递的是驱动程序注册表的**副本**。否则，人口普查局可能会将不是司机的新人加入名单，破坏 DMV 的记录。

为了应对这种情况，考虑更灵活的泛型类型是有用的。到目前为止我们看到的规则是相当严格的。