子类重写父类方法时返回值必须遵循类型兼容规则:基本类型和void必须完全一致;引用类型支持协变返回,可返回子类类型;泛型不协变,需谨慎处理;必须使用@Override注解确保编译期校验。

子类重写父类方法时,返回值不能随意更改,必须遵循 Java 的类型兼容规则——这不是靠配置实现的,而是由编译器在编译期直接校验的语法特性。
基本类型和 void 必须完全一致
如果父类方法返回的是 int、boolean、double 等基本类型,或者 void,那么子类重写时返回类型必须一字不差:
- 父类:
public int getId()→ 子类只能写public int getId() - 父类:
public void log()→ 子类只能写public void log() - 不允许改成
Integer、long或Object,哪怕存在自动装箱或向上转型也不行
引用类型支持协变返回(JDK 5+)
当父类方法返回引用类型(如类、接口)时,子类可返回其更具体的子类型,这是 Java 的协变返回(Covariant Return Type)特性:
- 父类返回
Animal,子类可返回Dog(Dog extends Animal)✅ - 父类返回
List<String>,子类可返回ArrayList<String>(因为ArrayList是List的实现类)✅ - 但父类返回
String,子类不能返回Object❌(范围扩大,违反里氏替换)
泛型返回值要特别小心
泛型本身不协变,类型参数必须严格匹配或满足继承关系:
- 父类返回
List<Number>→ 子类不能直接返回List<Integer>❌(List<Integer>不是List<Number>的子类) - 但可以返回
ArrayList<Integer>,前提是父类方法签名中返回的是List接口 ✅ - 更稳妥的做法是保持泛型类型一致,或改用非泛型的具体类型(如直接返回
Integer)
务必加上 @Override 注解
这个注解不是装饰,而是关键的安全锁:
- 它让编译器检查:方法名、参数列表、返回类型是否真能匹配父类方法
- 拼错方法名(如
hashcode())、参数类型写成Integer而非int、返回类型不满足协变,都会立刻报错 - 没有它,错误可能被掩盖为“新方法”,导致多态失效、逻辑静默出错

















