java中extends仅支持单继承,子类继承非私有成员但不继承构造器和static方法;重写需放宽访问权限、协变返回类型,并用super调用父类逻辑;字段遮蔽需用super.field访问父类字段。

Java 中 extends 的基本写法和限制
Java 里一个类只能用 extends 继承一个父类,不支持多继承。子类会自动获得父类的非私有成员(public、protected、包内默认访问权限的字段和方法),但 private 成员不可直接访问。
常见错误是误以为 extends 能继承构造器——它不能。子类必须显式或隐式调用父类构造器,否则编译报错:Implicit super constructor xxx() is undefined。
- 若父类只有带参构造器,子类构造器第一行必须写
super(...) - 子类不能继承父类的
static方法,但可以同名“隐藏”(不是重写) -
final类不能被extends,比如String或你自己加了final的类
重写(Override)时 super 和访问修饰符的关键细节
子类重写父类方法时,访问权限不能比父类更严格:比如父类是 protected,子类不能改成 private;但可以更宽松(如改为 public)。返回类型需兼容(协变返回类型允许子类返回更具体的类型)。
容易忽略的是:重写时若想复用父类逻辑,必须用 super.methodName() 显式调用,而不是直接写方法名——后者会触发递归调用自己,导致栈溢出。
- 重写
toString()、equals(Object)、hashCode()时,建议先用super.toString()拼接,避免丢掉父类状态 - 重写
clone()时,若父类已实现深拷贝逻辑,应调用super.clone()再处理子类字段 - 没加
@Override注解时,拼错方法名(比如hashcode())不会报错,但实际没重写成功
字段遮蔽(Field Hiding)与 this/super 的区分
当子类声明了和父类同名的字段(无论类型是否相同),会发生字段遮蔽:子类实例中存在两份独立字段,访问时取决于引用类型。例如 Parent p = new Child(); p.field 取的是父类字段值;而 Child c = new Child(); c.field 取的是子类字段值。
这种设计极易引发 bug,因为看起来像“覆盖”,实则毫无关系。调试时如果发现字段值“莫名其妙没变”,大概率是字段遮蔽 + 忘记用 super.field 访问父类版本。
- 子类方法中访问同名字段,默认是
this.field,即子类自己的字段 - 要明确读取父类字段,必须写
super.field(前提是父类字段不是private) - 字段不应被设计为可继承扩展点,优先用 getter/setter +
protected方法暴露行为
接口实现与 extends 的混用场景
类定义里 extends 只能出现一次(指定父类),但可以同时用 implements 接多个接口。注意语法顺序:class A extends B implements C, D —— extends 必须在 implements 前。
当父类已实现某个接口方法,子类继承后自动具备该能力;但如果子类需要改变行为,仍需重写,此时父类实现只是默认逻辑,不是强制约束。
- 父类实现了
Comparable,子类不必再implements Comparable,但可重写compareTo() - 若父类方法抛出异常
IOException,子类重写时只能缩小异常范围(如不抛、或只抛FileNotFoundException),不能扩大 - 泛型父类如
class Box<t> extends Container<t></t></t>,子类可固定类型:class StringBox extends Box<string></string>










