# 泛型和子类型化
以下代码合法吗?
List<String> ls = new ArrayList<String>(); // 1
List<Object> lo = ls; // 2
1
2
2
第一行是合法的,对于第二行,大多数人的本能反应是可以的。继续看看下面的代码
lo.add(new Object()); // 3
String s = ls.get(0); // 4: 尝试将 Object 赋值给字符串
1
2
2
这里通过 lo 访问 ls,也就是说,第三行:ls 里面被添加进了一个 Object 对象,第 4 行,将 Object 对象赋值给 String 对象。通过 lo 可以插入任意对象,结果已经不再是 String 了。
所以 Java 编译器防止这种情况的产生,第 2 行将导致编译时错误。
通常,如 Foo 是 Bar 的子类,并且 G 是一个泛型类型声明,G <Foo>
并非是 G <Bar>
的子类型。这可能是你学习泛型最困难的事情,因为他违背了我们一贯的直觉。
有一个例子可以帮助你来理解:
- Driver 驾驶员是 Person 人类的子类
List<Driver>
如果是等同于List<Person>
那么:不是驾驶员的人员可能被添加到列表中,这是很危险的事情;不会开车的人成为了驾驶人员。
为了应对这种情况,考虑更灵活的泛型类型很有用。到目前为止,我们看到的规则非常严格。