个人总结:
1.子类构造方法中没有显式使用super,java 也会默认调用父类的无参构造方法
2.当父类中没有无参构造方法,只有有参构造方法时,子类构造方法就必须显式地使用super来调用父类的有参构造方法。
3.如果父类没有定义任何构造方法,编译器会自动为父类生成一个无参构造方法。但如果父类已经定义了有参构造方法,编译器不会自动生成无参构造方法,此时子类必须显式调用父类的有参构造方法。
在 java 的面向对象编程世界里,继承是一个极为重要的特性,它让代码得以复用和扩展,构建出层次分明的类体系。而super关键字,就像是一把神奇的钥匙,在继承的场景中发挥着不可或缺的作用。它能够帮助我们轻松访问父类的成员,理解和掌握super关键字,对于编写高效、健壮的 java 代码至关重要。接下来,我们就深入探究一下super关键字的奥秘。
一、super 关键字的基本概念
super是 java 中的一个关键字,它主要用于在子类中访问父类的成员,包括成员变量、成员方法以及构造方法 。需要明确的是,super代表的是对当前对象父类对象的引用,但它并不像普通对象引用那样可以随意使用,它有着特定的使用场景和规则。
二、super 调用父类构造方法
在类的继承关系中,当创建子类对象时,会先调用父类的构造方法,然后再调用子类自身的构造方法,这是 java 对象初始化的一个重要机制。而super关键字可以在子类构造方法中显式地调用父类的构造方法。
1. 无参构造方法调用
先来看一个简单的例子,定义一个父类animal:
class animal { public animal() { system.out.println("animal类的无参构造方法被调用"); } }
再定义一个子类dog继承自animal:
class dog extends animal { public dog() { system.out.println("dog类的无参构造方法被调用"); } }
在测试类中创建dog对象:
public class main { public static void main(string[] args) { dog dog = new dog(); } }
运行结果为:
animal类的无参构造方法被调用
dog类的无参构造方法被调用
可以看到,在创建dog对象时,即使子类构造方法中没有显式使用super,java 也会默认调用父类的无参构造方法。这是 java 的一个隐式规则,目的是确保父类对象先完成初始化,为子类对象的初始化提供基础。
2. 有参构造方法调用
当父类中没有无参构造方法,只有有参构造方法时,子类构造方法就必须显式地使用super来调用父类的有参构造方法。例如,修改animal类:
class animal { private string name; public animal(string name) { this.name = name; system.out.println("animal类的有参构造方法被调用,动物名称:" + name); } }
然后修改dog类的构造方法:
class dog extends animal { public dog(string name) { super(name); system.out.println("dog类的有参构造方法被调用"); } }
测试代码如下:
public class main { public static void main(string[] args) { dog dog = new dog("旺财"); } }
运行结果:
animal类的有参构造方法被调用,动物名称:旺财
dog类的有参构造方法被调用
在子类dog的构造方法中,super(name)这行代码明确指定了调用父类animal的有参构造方法,并将参数传递过去,这样才能正确完成对象的初始化过程。同时要注意,super调用父类构造方法的语句必须是子类构造方法的第一行代码 ,否则会编译报错。
三、super 访问父类成员变量
当子类中定义了与父类同名的成员变量时,如果在子类中直接访问该变量名,默认访问的是子类自身的成员变量。此时,如果想要访问父类的同名成员变量,就可以使用super关键字。
定义父类person:
class person { string name = "父类的姓名"; }
定义子类student继承自person:
class student extends person { string name = "子类的姓名"; public void printnames() { system.out.println("子类的name:" + name); system.out.println("父类的name:" + super.name); } }
测试代码:
public class main { public static void main(string[] args) { student student = new student(); student.printnames(); } }
运行结果:
子类的name:子类的姓名
父类的name:父类的姓名
通过super.name,我们在子类student中成功访问到了父类person的成员变量name,避免了变量访问的混淆。
四、super 调用父类成员方法
同样,当子类重写了父类的方法时,如果在子类中想要调用父类被重写的方法,也可以借助super关键字。
定义父类vehicle:
class vehicle { public void run() { system.out.println("车辆在行驶"); } }
定义子类car继承自vehicle并重写run方法:
class car extends vehicle { @override public void run() { super.run(); system.out.println("汽车在马路上快速行驶"); } }
测试代码:
public class main { public static void main(string[] args) { car car = new car(); car.run(); } }
运行结果:
车辆在行驶
汽车在马路上快速行驶
在子类car的run方法中,super.run()调用了父类vehicle的run方法,这样既保留了父类方法的功能,又在其基础上进行了扩展,实现了代码的复用和增强。
五、父类定义有参、无参构造方法的各种情况
在 java 中,如果父类没有定义任何构造方法,编译器会自动为父类生成一个无参构造方法。但如果父类已经定义了有参构造方法,编译器不会自动生成无参构造方法,此时子类必须显式调用父类的有参构造方法。
1.关键规则总结:
父类情况 | 子类构造方法中是否显式调用super() | 结果 |
---|---|---|
有无参构造方法 | 未显式调用super() | 编译器自动插入super(); (调用父类无参构造) |
有参构造方法但没有无参构造方法 | 未显式调用super() | ❌ 编译错误:找不到父类的无参构造方法 |
有参构造方法但没有无参构造方法 | 显式调用super(参数); | ✅ 正确:调用父类的有参构造方法 |
2.示例代码分析
父类没有定义任何构造方法
class parent { // 编译器会自动添加无参构造方法: // public parent() {} } class child extends parent { public child() { // 编译器会自动插入 super(); } }
父类只有有参构造方法
class parent { public parent(int value) { // 定义了有参构造方法 // ... } // 注意:编译器不会自动生成无参构造方法! } class child extends parent { public child() { // ❌ 编译错误:没有super(),但父类没有无参构造方法 } public child(int value) { super(value); // ✅ 必须显式调用父类的有参构造方法 } }
3. 常见错误案例
以下代码会导致编译错误:
class animal { private string name; public animal(string name) { // 父类只有有参构造 this.name = name; } } class dog extends animal { public dog() { // ❌ 编译错误:没有super(),但父类没有无参构造 } }
修正方式:在子类构造方法中显式调用父类的有参构造方法
class dog extends animal { public dog(string name) { super(name); // ✅ 显式调用父类的有参构造 } }
六、super( )详解
1.super() 是什么?
在 java 中,super()
是子类构造方法中调用父类构造方法的特殊语法。它必须是子类构造方法的第一行代码。
2.为什么需要 super()?
当创建子类对象时,java 会先初始化父类的部分。通过super()
,我们可以显式指定如何初始化父类的状态。
3.最简单的示例
下面是一个基础示例,展示super()
的基本用法:
// 父类:动物 class animal { private string name; // 父类的构造方法 public animal(string name) { this.name = name; system.out.println("创建了一只动物:" + name); } public string getname() { return name; } } // 子类:狗 class dog extends animal { private string breed; // 子类的构造方法 public dog(string name, string breed) { super(name); // 调用父类的构造方法,必须在第一行 this.breed = breed; system.out.println("这是一只" + breed + ":" + name); } public string getbreed() { return breed; } } // 测试类 public class main { public static void main(string[] args) { dog dog = new dog("旺财", "金毛"); system.out.println(dog.getname() + "是一只" + dog.getbreed()); } }
4.关键代码解释
父类构造方法:
public animal(string name) { this.name = name; }
animal
类的构造方法接收一个name
参数,用于初始化动物的名称。
子类构造方法中的super()
:
public dog(string name, string breed) { super(name); // 调用父类构造方法,初始化name this.breed = breed; // 初始化子类特有的属性 }
super(name)
将name
参数传递给父类的构造方法,确保父类的name
字段被正确初始化。
如果省略super(name)
,java 会默认调用父类的无参构造方法(如果存在)。
5.执行流程
当执行dog dog = new dog("旺财", "金毛");
时:
- 调用子类构造方法:
dog(string name, string breed)
- 隐式 / 显式调用父类构造方法:
- 通过
super(name)
调用animal(string name)
- 父类初始化完成:
animal
的name
字段被设置为 "旺财"- 继续执行子类构造方法:
this.breed = breed
将breed
设置为 "金毛"
到此这篇关于java 中的 super 关键字的文章就介绍到这了,更多相关java super 关键字内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!