java中extends继承时子类无法访问父类private成员是设计使然,非bug;需通过protected修饰、getter/setter或组合替代;重写tostring/equals/hashcode须调用super版本;接口继承用extends,实现用implements;子类构造器默认调用super(),父类无无参构造器时会编译失败。

Java里用extends继承类时,子类拿不到父类private成员
这不是bug,是设计使然。private字段或方法只对定义它的类可见,子类哪怕写了extends也完全访问不到。常见错误是子类里直接写super.privateField,编译直接报cannot resolve symbol。
如果真需要复用,有三个实际选择:
- 把父类字段改成
protected(最常用,但要确认语义合理) - 提供
public或protected的getter/setter方法 - 改用组合(
has-a)代替继承(is-a),比如在子类里持有一个父类实例
重写toString()、equals()这些方法时,不调用super版本容易出错
父类可能已经实现了关键逻辑,比如Object.equals()处理null,Throwable.toString()拼接异常信息。子类重写时漏掉super.equals(),会导致行为不一致甚至NPE。
典型场景:自定义实体类继承java.util.Date或Exception后重写toString(),结果打印出来缺了时间戳或堆栈前缀。
- 重写
toString():建议开头加super.toString() + " | "再拼自己的字段 - 重写
equals():先if (!super.equals(obj)) return false;,再检查子类特有字段 - 重写
hashCode():必须和equals()保持一致,否则放进HashSet会失效
接口和抽象类都用extends?不对,接口用extends,实现用implements
Java语法上,类继承类用extends,类实现接口用implements,接口继承接口才用extends。写反了编译器会立刻报错:error: <code>class cannot extend an interface。
容易混淆的点在于:一个类可以extends一个父类,同时implements多个接口;而接口可以extends多个其他接口(用逗号分隔)。
-
class A extends B implements C, D✅ -
interface X extends Y, Z✅ -
class A extends B, C❌(Java不支持多继承) -
class A implements B extends C❌(语法顺序错)
父类构造器没被显式调用,编译器自动插super()但可能失败
子类构造器第一行,如果没写this(...)或super(...),编译器会默认补一个super()——也就是无参构造器。一旦父类删掉了无参构造器(比如只留了public Parent(String name)),子类编译就直接失败:constructor Parent() is not defined。
这不是IDE的提示问题,是javac强制规则。尤其在用Lombok的@RequiredArgsConstructor或手动删了默认构造器时特别容易踩坑。
- 解决办法:子类构造器第一行明确写
super(参数) - 或者,父类保留一个
protected Parent() { }(如果语义允许) - 注意:
super()和this()不能共存,也不能出现在第二行以后
extends背后是JVM的类加载和方法表查找机制,很多问题其实卡在语义理解偏差上。Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











