Java-super关键字
1、访问父类的构造函数:
当子类的构造函数需要调用父类的构造函数时,可以使用 super()
关键字。
2、访问父类的方法和属性:
如果子类重写了父类的方法或属性,但仍想在子类中访问父类的版本,可以使用 super
关键字。
使用实例
Animal.java
public class Animal {
String name;
// 构造函数
Animal(String name) {
this.name = name;
}
// 父类的方法
void sound() {
System.out.println("动物的声音");
}
}
Dog.java
public class Dog extends Animal{
// breed 品种
String breed;
// 子类构造函数
//在Dog类的构造函数中调用super(name),
// 这是为了初始化Animal类中的name属性。
// 这样,Dog类就可以继承父类的属性和方法。
Dog(String name, String breed) {
// 调用父类的构造函数
super(name);
this.breed = breed;
}
// 重写父类的方法
@Override
void sound() {
// 使用super调用父类的sound方法
super.sound(); // 调用Animal类中的sound方法
System.out.println("汪!汪!");
}
void displayInfo() {
System.out.println("Name: " + name + ", Breed: " + breed);
}
}
Main.java
public class Main {
public static void main(String[] args) {
// 创建Dog对象
Dog dog = new Dog("伙伴", "金毛猎犬");
// 调用方法
dog.displayInfo();
dog.sound();
}
}
打印结果
Name: 伙伴, Breed: 金毛猎犬
动物的声音
汪!汪!
3、解释代码
在Dog类的构造函数中调用super(name),这是为了初始化Animal类中的name属性。Dog类就可以继承父类的属性和方法。
当我们使用 super(name);
时,我们是在调用父类(Animal)的构造函数。这样做的结果是:
-
初始化父类的属性:
在父类Animal中,有一个字符串属性name。通过调用
super(name)
,我们把由Dog类的构造函数传入的name参数(比如“伙伴”)传递给父类的构造函数,这样Animal类中的name属性就会被赋值为“伙伴”。 -
确保父类的构造逻辑被执行:
super(name)
调用父类的构造函数时,会执行父类构造函数的逻辑(即Animal类中的构造函数体)。如果父类有一些必要的初始化逻辑(比如连接数据库、设置某些默认值等),这些逻辑在子类构造时也会被执行,确保父类对象的完整初始化。
执行过程:
-
创建Dog对象:
当我们在main方法中创建Dog对象时,调用了
new Dog("伙伴", "金毛猎犬")
。
Dog dog = new Dog("伙计", "金毛猎犬");
-
调用Dog构造函数:
进入Dog的构造函数,执行
Dog(String name, String breed)
。
Dog(String name, String breed) {
// 调用父类的构造函数
super(name);
this.breed = breed;
}
-
执行super(name):
这行代码触发了Animal类的构造函数
Animal(String name)
的调用。
name参数值“伙伴”被传递给Animal的构造函数,用于初始化Animal的name属性。
Animal(String name) {
this.name = name;
}
-
初始化父类属性:
在Animal的构造函数中,this.name = name; 这行代码执行后,name属性会被赋值为“伙伴 ”。此时,Animal对象被成功创建,Animal中的name字段现在有了具体的值。
-
返回到Dog构造函数继续执行:
继续执行Dog类构造函数中的剩余代码,
this.breed = breed
; 被执行,breed属性被赋值为“金毛猎犬”。
总结来说,super(name);是确保Dog类能够正确初始化其父类Animal的部分,并且可以访问和使用在父类中定义的属性和方法。
关键字 | 访问成员变量 | 访问构造方法 | 访问构造方法 |
---|---|---|---|
this | this.成员变量 访问本类成员变量 |
this(...) 访问本类构造方法 |
this.成员方法(...) 访问本类成员方法 |
super | super.成员变量 访问父类成员变量 |
super(...) 访问父类构造方法 |
super.成员方法(...) 访问父类成员方法 |
4、问题一:
子类的所有构造方法默认都会访问父类中无参的构造方法,如果父类中无无参构造方法,子类就无法实例化。这是为什么呢?
- 因为子类会继承父类的所有构造方法,可能还会使用父类中的数据,所以在子类初始化之前,一定要完成父类的初始化
- 每一个子类的构造方法中第一条的默认语句是
super()
- 在Java中,子类的构造方法中,如果没有显式地调用父类的构造方法(即没有使用
super()
),编译器会自动在构造方法的开头插入一行super()
; 的代码。这意味着,子类在创建实例时,父类的默认构造函数会被调用。
①默认构造函数:
如果父类有一个无参构造函数(即没有参数的构造函数),那么在子类构造方法中没有显式调用 super()
的情况下,Java编译器会自动插入 super()
;。
如果父类没有无参构造函数但有带参数的构造函数,则子类必须显式地调用父类构造函数(例如:super(arg1, arg2)
;)。
②编译器的行为:
当你定义一个子类的构造方法,而没有调用任何父类的构造方法时,Java编译器会检查父类是否有无参构造函数。如果有,它会插入一行 super()
;,以确保父类的初始化逻辑被执行。
评论区