协变返回类型指子类重写父类方法时可将返回类型声明为父类返回类型的子类型,自Java 5起支持;要求方法签名完全一致、返回类型为父类返回类型的子类、仅适用于重写且父类方法非private或static。

Java 中方法重写(Override)时,返回值类型必须遵循协变返回类型(Covariant Return Type)规则:子类重写父类方法的返回值类型可以是父类方法返回值类型的子类型,但不能是无关类型或父类型。
什么是协变返回类型
协变返回类型允许子类在重写方法时,将返回值类型缩小为更具体的子类类型,前提是该类型与父类方法的返回类型存在继承关系。这是 Java 5 引入的特性,提升了类型安全和代码表达力。
- 父类方法返回 Object,子类可重写为返回 String、List 等其子类
- 父类返回 Number,子类可返回 Integer 或 Double
- 但不能将 String 重写为 Object(逆变,不合法)
- 也不能返回完全无关的类型,如父类返回 Date,子类返回 String
语法要求与编译检查
重写方法的签名(方法名、参数列表)必须完全一致,仅返回值类型可协变。JVM 在运行期仍按父类声明的类型处理,但编译器会确保调用方获得更精确的类型信息。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 必须使用 @Override 注解,否则编译器可能报错或误判为重载
- 若返回类型不满足协变规则,编译直接失败,例如:
return type is incompatible with ... - 泛型类型需注意:返回 List
不能重写 List —— 泛型是不可变的,二者无继承关系
常见应用场景
协变常用于构建更自然的 fluent API 或框架扩展点,让子类方法返回自身类型,支持链式调用。
- Builder 模式中,父 Builder 返回 Builder,子类重写为返回 ConcreteBuilder
- 克隆方法:父类声明 protected Object clone(),子类可重写为 public MyClass clone()
- 集合工厂方法:父类返回 Collection
,子类返回 ArrayList (需注意泛型擦除限制,实际常用接口类型)
注意事项与陷阱
看似简单,但容易在泛型、数组、原始类型场景出错。
- 基本类型不支持协变:父类返回 int,子类不能返回 long 或 Integer
- 数组类型协变有限:父类返回 Object[],子类可返回 String[];但 String[] 和 Object[] 是运行期协变的,编译期也允许,不过要小心类型擦除影响
- 不要混淆重写与重载:改变返回类型但不改参数列表,不是重载,而是非法重写;编译器不会接受
- IDE 和 Lombok 等工具生成代码时,需确认生成的重写方法是否满足协变约束
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










