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