泛型与继承
泛型类型之间不存在继承关系,这是理解泛型类型安全的关键。
泛型类型不继承
Java
// 错误理解:List<String> 不是 List<Object> 的子类
List<String> strings = new ArrayList<>();
List<Object> objects = strings; // 编译错误
// 原因:如果允许,会有类型安全问题
// objects.add(new Integer(1)); // 放入 Integer
// String s = strings.get(0); // 取出 Integer,类型错误!
泛型不变性:List 和 List 没有继承关系,互不兼容。
类型安全示例
Java
// 如果允许赋值(假设)
List<String> strings = new ArrayList<>();
List<Object> objects = strings; // 如果编译通过
objects.add(new Integer(100)); // 向 Object 列表添加 Integer
String s = strings.get(0); // 从 String 列表取出 Integer → 类型错误!
// Java 编译器禁止这种赋值,保证类型安全
数组的协变
数组是协变的(有继承关系):
Java
// 数组协变:String[] 是 Object[] 的子类
String[] strings = new String[10];
Object[] objects = strings; // 允许
objects[0] = new Integer(100); // 运行时抛 ArrayStoreException
数组协变问题:编译通过但运行时出错。泛型不变性避免了这种问题。
| 特性 | 数组 | 泛型 |
|---|---|---|
| 继承关系 | 协变(有继承) | 不变(无继承) |
| 类型安全 | 运行时检查 | 编译期检查 |
| 错误时机 | 运行时抛异常 | 编译期禁止 |
类型继承示例
Java
// 类型参数的继承关系不影响泛型类继承
class Animal {}
class Dog extends Animal {}
// Dog 是 Animal 的子类
Dog dog = new Dog();
Animal animal = dog; // ✅ 允许
// 但 List<Dog> 不是 List<Animal> 的子类
List<Dog> dogs = new ArrayList<>();
List<Animal> animals = dogs; // ❌ 编译错误
使用通配符实现"继承"
Java
List<Dog> dogs = new ArrayList<>();
// 使用上界通配符
List<? extends Animal> animals = dogs; // ✅ 允许
// 但只能读取,不能添加
Animal a = animals.get(0); // ✅ 读取
animals.add(new Dog()); // ❌ 不能添加
泛型类继承规则
泛型类之间的继承
Java
// 泛型类继承
public class Box<T> {}
public class SpecialBox<T> extends Box<T> {} // 继承泛型类
// 指定具体类型继承
public class StringBox extends Box<String> {} // 指定类型
实现泛型接口
Java
public interface Generator<T> {}
// 指定类型实现
public class StringGenerator implements Generator<String> {}
// 保留泛型实现
public class GenericGenerator<T> implements Generator<T> {}
协变与逆变
| 概念 | 说明 | Java 实现 |
|---|---|---|
| 协变 | 子类关系保留 | <? extends T> |
| 逆变 | 子类关系反转 | <? super T> |
| 不变 | 无继承关系 | 泛型默认不变 |
Java
// 协变:List<? extends Animal> 可接收 List<Dog>
List<? extends Animal> animals = new ArrayList<Dog>(); // ✅
// 逆变:List<? super Dog> 可接收 List<Animal>
List<? super Dog> list = new ArrayList<Animal>(); // ✅
要点总结
- 泛型不变性:List 不是 List 的子类
- 类型参数的继承不影响泛型类继承
- 数组协变,泛型不变
- 协变用 <? extends T>,逆变用 <? super T>
- 泛型在编译期保证类型安全,数组在运行时检查
- 泛型类可继承泛型类或指定类型继承
📝 发现内容有误?点击此处直接编辑