继承本质是“is-a”关系建模,要求行为可替代性(里氏替换原则),支持结构化复用与运行时多态,java采用单继承并辅以接口实现多重契约。

继承的本质是“is-a”关系的建模
Java中继承不是简单的功能搬运,而是对现实世界层级关系的抽象表达。比如Dog is a Animal、Student is a Person,这种语义约束决定了能否继承——不能因为“汽车有轮子,自行车也有轮子”就让Car继承Bicycle,那属于“has-a”关系,该用组合而非继承。
真正合理的继承必须满足行为可替代性:任何使用父类对象的地方,换成子类对象后,程序逻辑依然成立(里氏替换原则)。这也是为什么重写方法时,子类不能缩小访问权限、不能抛出父类未声明的检查型异常。
继承的核心价值在于结构化复用
它把多个类的共性抽离到父类,避免重复定义相同字段和通用逻辑。例如Cat和Dog都需name、age、eat()、sleep(),若各自实现,不仅冗余,而且修改一处就得同步改多处。
- 子类自动获得父类的public和protected成员(变量与方法)
- private成员不可直接访问,但可通过父类提供的public/protected getter/setter间接使用
- 构造器不被继承,但子类构造器必须显式或隐式调用super()来初始化父类部分
继承机制背后的关键规则
Java采用单继承模型:一个类只能有一个直接父类。这避免了多继承带来的歧义(如菱形继承问题),同时通过接口支持多重行为契约。
方法重写(Override)是继承中实现多态的基础,需满足:
- 方法签名完全一致(名称+参数列表)
- 返回类型兼容(支持协变返回,如父类返回Animal,子类可返回Dog)
- 访问权限不能更严格(public → protected ❌,但protected → public ✅)
- 建议始终添加@Override注解,由编译器校验是否真正在重写
别忽略内存与执行层面的真实表现
创建子类对象时,JVM会先为父类部分分配空间并调用其构造器,再初始化子类独有字段。这意味着父类初始化逻辑总是优先执行。
方法调用走的是运行时绑定:如果子类重写了某方法,哪怕用父类引用指向子类对象(如Animal a = new Dog()),调用a.eat()实际执行的仍是Dog中的eat()实现。这个机制正是多态的根基。
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











