Java仅实例化父类却报子类继承相关构造器错误的原因是什么?
问题根本原因
这个报错属于编译阶段的语法规则校验失败,和你运行时有没有实例化Bar类没有任何关系:Java编译器会对源码中定义的所有类做语法合法性检查,只要类的定义不符合Java规范,哪怕你完全不用这个类,也会直接阻断编译流程。
核心原理梳理
1. Java构造器的继承规则
- 当你没有给类写任何自定义构造器时,Java会自动生成一个无参的默认构造器;但只要你手动写了任意一个自定义构造器(比如你这里给Foo写了有参构造
public Foo(int a)),Java就不会再自动生成无参构造器,此时Foo类只有一个接收int参数的构造器。 - 所有子类的构造器,第一行必须先调用父类的构造器:如果你没有手动写
super()相关的调用,编译器会自动在子类构造器的第一行插入super(),也就是调用父类的无参构造器。 - 你写的Bar类是空实现,编译器会自动给Bar生成默认的无参构造器,最终生成的隐式代码是:
class Bar extends Foo { public Bar() { super(); // 编译器自动插入,调用父类无参构造 } }
此时父类Foo没有无参构造器,这行自动生成的super()找不到匹配的构造方法,就触发了你看到的编译报错。
两种修改方案生效的原因
方案1:给Foo添加无参构造器
此时父类存在无参构造器,编译器给Bar自动插入的super()可以正常匹配到构造方法,语法合法,编译通过。
方案2:给Bar手动写调用父类有参构造的构造器
class Bar extends Foo { public Bar(int a) { super(a); // 手动指定调用父类的有参构造 } }
当你手动在子类构造器第一行写了super(a),编译器就不会再自动插入super(),此时调用的是父类已经存在的Foo(int a)构造器,语法合法,编译通过。
为什么没用到Bar也需要保证它的语法合法?
Java的编译校验是全源码级别的,只要你在源码里定义了Bar这个类,编译器就必须检查它的语法是否符合规范,和你后续会不会实例化、会不会用到这个类完全无关,语法不合法的代码根本不会进入后续的运行环节。
内容的提问来源于stack exchange,提问作者Oblivion
相关产品推荐
相关产品推荐

