子类覆盖父类方法时返回值类型必须严格兼容:基本类型和void必须完全相同;引用类型允许协变(如Animal→Dog),禁止逆变;泛型不协变,需保持类型参数一致;务必使用@Override注解确保重写正确。

子类覆盖父类方法时,返回值类型不能随意更改,必须满足严格的兼容性规则——不是“能改什么”,而是“只能怎么改”。核心在于:基本类型和 void 必须完全一致;引用类型允许“缩小”(协变),但绝不允许“扩大”。
基本类型和 void 必须一字不差
父类方法若返回 int、boolean、double 等基本类型,或声明为 void,子类重写时返回类型必须严格相同:
- 父类是
public int getId()→ 子类只能写public int getId() - 父类是
public void log()→ 子类只能写public void log() - 不允许改成
Integer、long、Object,哪怕存在自动装箱或向上转型也不行
引用类型支持协变返回(JDK 5+)
当父类返回引用类型时,子类可返回其更具体的子类,这是合法且推荐的协变行为:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 父类:
public Animal getPet()→ 子类可写public Dog getPet()(Dog extends Animal)✅ - 父类:
public List<string> getData()</string>→ 子类可写public ArrayList<string> getData()</string>✅ - 但父类返回
String,子类返回Object❌(范围扩大,编译失败)
泛型返回值要特别小心
泛型本身不协变,类型参数需匹配。常见误区是认为 List<integer></integer> 是 List<number></number> 的子类,实际不是:
立即学习“Java免费学习笔记(深入)”;
- 父类:
public List<number> numbers()</number>→ 子类不能直接返回List<integer></integer> - 正确做法:保持原泛型类型,或返回具体非泛型子类(如
public Integer getValue()),或用通配符设计接口
务必加上 @Override 注解
这个注解不是装饰,而是编译期安全锁:
- 一旦返回类型不满足协变规则,立即编译报错
- 同时还能捕获方法名拼错、参数列表不一致等隐式重载问题
- 不加它,可能看似“运行正常”,实则根本没重写成功

















