Java泛型类继承中类型传递分两种:子类保留泛型参数(可加约束)或固定具体类型;类型擦除导致运行时无法区分不同泛型实例,仅编译期生效。

Java 泛型类在继承体系中传递类型,关键在于子类如何声明对父类泛型参数的处理方式:要么保留类型参数继续泛化,要么具体化为某个实际类型。这种传递不是运行时行为,而是在编译期由编译器检查并落实的类型约束。
子类保留泛型参数,延续类型可变性
这种方式让子类仍具备通用性,能适配多种类型,同时复用父类逻辑。
- 父类定义泛型参数(如
<T>),子类继承时也声明自己的类型参数,并将其传递给父类 - 可添加新的边界限制(如
T extends Comparable<T>),增强类型表达能力 - 示例:
class Repository<T> { void save(T item) { /* ... */ } } class PagingRepository<T extends Serializable> extends Repository<T> { /* T 仍为泛型,但加了约束 */ }
子类固定具体类型,实现类型特化
子类将父类的类型参数“实化”,使整个继承链在该分支上获得明确类型语义。
- 类型安全直接生效:所有继承方法自动适配该类型,无需强制转换
- 编译器据此禁止传入不匹配的值
- 示例:
class UserRepository extends Repository<User> { void saveUser(User u) { save(u); } // save() 参数已确定为 User }
类型参数在继承中不能被“覆盖”,只能被约束或实例化
- Java 不允许子类重新定义同名类型参数(如父类有
<T>,子类再写<T>不是覆盖,而是隐式继承) - 若父类类型参数有上界(如
<T extends Number>),子类继承时可保持、收紧(如extends Integer),但不能放宽(如去掉extends Number) - 子类不能引入与父类冲突的类型约束,否则编译失败
注意类型擦除带来的实际限制
- 运行时无法通过
getClass()或instanceof区分Repository<String>和Repository<Integer>,它们都擦除为Repository - 因此,类型传递只影响编译检查和方法签名生成(如桥接方法),不改变运行时类结构
- 若需运行时获取泛型信息(如反序列化场景),需借助
TypeReference、ParameterizedType等反射手段,而非依赖继承本身
不复杂但容易忽略
立即学习“Java免费学习笔记(深入)”;


















