一、父类中没有定义任何构造方法
代码示例:
// 父类
class Vehicle{}
// 子类
class Car extends Vehicle{
private String name;
public Car(String name) {
this.name = name;
}
@Override
public String toString() {
return "car name: " + this.name;
}
}
public class VehicleTest {
public static void main(String[] args) {
Vehicle v2 = new Car("A Car");
System.out.println(v2);
}
}
说明: 这里我们定义一个父类“Vehicle”,不包含任何的构造方法。实际上,编译器会自动给我们定义的“没有显示定义构造方法的类”去定义一个无参构造方法:
public Vehicle() {};
子类Car在创建实例 v2 时,会首先调用父类 Vehicle 的无参构造方法,创建一个 Vehicle 实例。第二步,调用子类 Car 的构造方法(含参),将上一步创建的 Vehicle 实例进行包装,成为一个 Car实例。第三步,执行 println(v2),此处会自动调用我们Car类中的 toString() 方法,这是由Object类决定的,这里写成 System.out.println(v2.toString())是一样的。
这里可以看到,我们定义一个类时,只给一个类定义无参构造方法,或者不定义任何构造方法是相同的。
二、父类中只定义了有参构造方法
代码示例:
// 父类
class Vehicle{
private String name;
// public Vehicle() {};
public Vehicle(String name){
this.name = name;
}
@Override
public String toString() {
return "vehicle name: " + this.name;
}
}
// 子类
class Car extends Vehicle{
private String name;
public Car(String name) {
super(name); # 调用父类有参构造
this.name = name;
}
@Override
public String toString() {
return "car name: " + this.name;
}
}
public class VehicleTest {
public static void main(String[] args) {
Vehicle v2 = new Car("A Car");
System.out.println(v2);
}
}
此处,我们可以看到子类中的构造方法中有一句 “super(name)”,这一句的功能是在显示的调用父类中的有参构造方法。如果我们注释掉这一行,IDE会报错:
是说“父类 Vehicle 中没有定义无参构造器,必须必须显式调用另一个构造函数”。出现这个错误的原因是因为,子类中的构造函数会默认尝试执行 super() 去调用父类的无参构造器 , 但是我们的父类中没有无参构造方法,那么这里就无法继承父类的无参构造。
问题来了:为什么“一、父类中没有定义任何构造方法” 中也没有定义无参构造就没有错误呢?
因为如果一个Java类,我们不定义任何的构造方法,JVM就会自动帮我们构建一个无参构造方法(不可见)。但是,如果我们主动创建了一个构造方法,无论是有参还是无参构造方法,Java虚拟机就会认为用户创建了自己需要的构造方法,就不会再帮助我们创建任何构造方法。
知道了原因,就容易得出解决方法 (以下任意一种均可):
- 我们可以显示调用父类中的有参构造方法 super(name);
- 在父类中定义一个无参构造方法 public Vehicle() {};
三、完整代码示例
// 父类
class Vehicle{
private String name;
public Vehicle() {};
public Vehicle(String name){
this.name = name;
}
@Override
public String toString() {
return "vehicle name: " + this.name;
}
}
// 子类
class Car extends Vehicle{
private String name;
public Car(String name) {
super(name);
this.name = name;
}
@Override
public String toString() {
return "car name: " + this.name;
}
}
public class VehicleTest {
public static void main(String[] args) {
Vehicle v1 = new Vehicle("A Vehicle");
System.out.println(v1);
Vehicle v2 = new Car("A Car");
System.out.println(v2.toString());
}
}
可以通过设置断点,用Debug模式查看代码具体工作流程。