extends 是 Java 中实现继承的唯一关键字,确立子类与父类的“is-a”关系;子类继承 public/protected 成员但不继承 private 成员和构造方法;必须显式调用 super() 若父类无无参构造;重写方法时访问权限不能变窄、异常不能扩大、返回类型可协变。

extends 是 Java 中实现继承的唯一关键字,它确立了子类与父类之间的“is-a”关系——子类是父类的一种具体化。这不是语法糖,而是编译器强制执行的类型契约:子类自动获得父类所有 public 和 protected 成员(字段、方法),但不继承 private 成员,也不继承构造方法。
为什么子类必须调用 super()?
Java 规定:每个子类构造方法的第一条语句,默认隐式插入 super()(即调用父类无参构造)。如果父类没有无参构造,编译器会直接报错:Implicit super constructor XXX() is undefined。
- 父类有无参构造 → 子类可省略
super(),自动调用 - 父类只有有参构造 → 子类必须显式写
super(...),且必须是第一行 - 多层继承时,构造链严格按“最顶层父类 → 中间父类 → 当前子类”顺序执行,像栈一样向下压入
class A {
A(String s) { System.out.println("A: " + s); }
}
class B extends A {
B() { super("hello"); } // 必须显式调用
}
class C extends B {
C() { super(); } // 这里 super() 实际调用的是 B(),而 B() 内部已调用 A("hello")
}
private 成员到底能不能被继承?
不能。这是高频误解。子类对象内存布局中**不包含父类 private 字段**,子类代码里也**无法通过 this.xxx 或 super.xxx 直接访问**。所谓“继承”,仅针对可访问成员生效。
- 想让子类安全使用敏感数据?在父类提供
protectedgetter/setter,而非暴露private字段 - 子类重写方法时若依赖父类私有状态,应通过父类公开方法间接操作,否则逻辑断裂
- IDE 显示“继承自父类”的字段提示,只是编辑器辅助,并不代表实际可访问
重写方法时最容易踩的三个权限陷阱
重写(@Override)不是随便改签名,JVM 在运行期靠方法签名+访问修饰符做动态绑定,违反规则会导致编译失败或行为异常。
立即学习“Java免费学习笔记(深入)”;
- 访问权限不能变窄:父类是
protected void run(),子类不能写成private void run()(编译错误) - 异常声明不能扩大:父类抛
IOException,子类只能抛FileNotFoundException(其子类),不能抛Exception - 返回类型支持协变:父类返回
Animal,子类可返回Dog(更具体的子类型),但参数类型必须完全一致
子类不是父类的“副本”,而是带约束的扩展容器;继承不是为了省几行代码,而是为了建立可验证的类型兼容关系。一旦发现需要频繁用 instanceof 判断子类类型、或子类大量覆盖父类逻辑却只保留空壳,就该怀疑:这里本该用组合或接口,而不是继承。










