协变返回类型允许子类重写父类方法时返回更具体的子类型,前提是父类返回引用类型、子类返回类型为其子类、方法签名一致且父类方法非private/static/final;适用于builder模式等链式调用和接口默认方法重写,提升类型安全与可读性。

子类重写父类方法时用协变返回类型,核心是让返回值更具体、更安全、更自然——不需要强制转型,编译器就能推断出精确类型。
协变返回类型的适用前提
不是所有重写都能用协变返回,必须同时满足:
- 父类方法返回的是引用类型(不能是基本类型或 void)
- 子类重写方法的返回类型必须是父类返回类型的**直接或间接子类**
- 方法名、参数列表、访问修饰符(不能更严格)完全一致
- 父类方法不能是 private、static 或 final
典型应用场景:链式调用与类型安全
比如构建器(Builder)模式或对象工厂方法,常靠协变返回避免冗余转型:
父类定义通用能力:class Vehicle {
Vehicle start() { return this; }
}
子类返回自身类型,调用链可直接延续:
class Car extends Vehicle {
@Override
Car start() {
System.out.println("Car engine started");
return this; // ✅ 返回 Car,不是 Vehicle
}
void honk() { System.out.println("Beep!"); }
}
这样就能写:new Car().start().honk(); —— 编译通过,无需 ((Car)new Car().start()).honk()。
接口默认方法也支持协变
Java 8+ 的接口默认方法被子类重写时,同样允许协变返回:
interface AnimalFactory {
default Animal create() { return new Animal(); }
}
class DogFactory implements AnimalFactory {
@Override
Dog create() { return new Dog(); } // ✅ 合法:Dog 是 Animal 子类
}
这使得接口设计更灵活,实现类能暴露更精确的返回类型。
注意边界情况
协变不改变多态本质,运行时仍按实际对象类型分派:
- 若用父类引用接收结果,变量静态类型仍是父类:
Animal a = new Dog().getOwner();→ a 是 Animal 类型 - 只有用子类引用接收,才能直接调用子类特有方法:
Dog d = new Dog().getOwner(); d.bark(); - 泛型类中的方法重写不自动触发协变(需显式声明类型参数约束)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











