一篇长文带你领略super 关键字

这是我参与11月更文挑战的第 11 天,活动详情查看:2021最后一次更文挑战

super和 this 可以对比着学习:

1,this

  • this 是一个引用,保存内存地址指向自己。
  • this 出现在实例方法中,谁调用这个实例方法,this 就代表谁,this 代表当前正在执行 这个动作的对象。
  • this 不能出现在静态方法中。
  • this 大部分情况下可以省略,在方法中区分实例变量和局部变量的时候不能省略。
  • “this(实际参数列表)”出现在构造方法第一行,通过当前的构造方法去调用本类当中 其它的构造方法。

2,super

  • 严格来说,super 其实并不是一个引用,它只是一个关键字,super代表了当前对象中 从父类继承过来的那部分特征。this 指向一个独立的对象,Super 并不是指向某个“独立” 的对象,假设张大明是父亲,张小明是儿子,有这样一句话:大家都说张小明的眼睛、鼻子和父亲很像。和父亲的很像。那么也就是说儿子继承了父亲的眼睛和鼻子特征,那么眼睛和鼻子肯定最终 还是长在儿子的身上。假设 this 指向张小明,那么 super就代表张小明身上的眼睛和鼻子。 换句话说 super 其实是 this 的一部分。
  • 举个栗子:张大明和张小明其实是两个独立的对象,两个对象内存方面没有联系,super 只是代表张小明对象身上的眼睛和鼻子,因为这个是从父类中继承过来的,在内存方面使用了 super 关键字进行了标记,对于下图来说“this.眼睛”和“super 眼睛”都是访问的同一块内存空间。
  • super 和 this 都可以使用在实例方法当中。
  • super 不能使用在静态方法当中,因为 super代表了当前对象上的父类型特征,静态方 法中没有 this,肯定也是不能使用 super的。
  • super 也有这种用法:“super(实际参数列表);” 这种用法是通过当前的构造方法调用父类的构造方法。

super和this 都可以使用在实例方法中,并且都不能使用在静态方法中,“this”大部分情况下都是可以省略的,只有在方法中区分局部变量和实例变量的时候不能省略。

看下面的代码进行体会学习:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
typescript复制代码//书
public class Book {
//书名
String name;
//构造方法
public Book(){
super();
}
public Book(String name){
super();
this.name= name;
}
//纸质羽书
public class PaperBook extends Book{
//构造方法
public PaperBook(){
super();
}
public PaperBook(String name){
super();
this.name = name;
}
//打印书名
public void printName(){
System.out.println("this.name->书名:"+ this.name); System.out.println("super.name->书名:"+ super.name);
}
}
public class BookTest{
public static void main(String[] args){
paperBook book1=new PaperBook("零基础学Java");
book1.printName();
}
}
//程序运行结果如下:
this.name->书名:零基础学Java
super.name->书名:零基础学Java

我们发现printName()方法中super.name和this.name最终输出结果是一样的,这是为什么呢?

因为this.name和super.name实际上是同一块内存空间,所以它们的输出结果是完全一样的。

通过上面的例子,我们最终得出一个结论:父类和子类中有同名实例变量或者有同名的实例方法,想在子类中访问父类中的实例变量或实例方法,则super 是不能省略的,其他情况都可以省略。

super 使用在构造方法中,语法格式为:super(实际参数列表),这行代码和“this(实际参数列表)”都是只允许出现在构造方法的第一行(这一点记住就行了),所以这两行代码是无法共存的。“super(实际参数列表)”这种语法表示子类构造方法执行过程中调用父类的构造方法。

下面来看一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
arduino复制代码public class People{
String idCand;
String name;
boalean sex;
public People(){

}
public People(String idCard,String name.,boolean sex ){
this.idCard = idCard;
this.name = name;
this.sex = sex;
}
public class Student extends People{
// 学号是子类特有的
int sno;
public Student(){

}
public Student(String idCard,String name,boolean sex,int sno){ this.idCard = idCard;
this.name = name;
this.sex=sex;
this.sno= sno;
}
}
public class StudentTest {
public static void main(Stringll args){
Student s = new Student("12345x","jack"true,100); System.out.printin("身份证号"+s.idCard); System.out.println("姓名"+s.name);
System.out.printin("性别“+ s.sex);
System.out.println("学号"+ s.sno);
}
}
//运行结果如下:
身份证号12345x
姓名jack
性别true
学号100

通过以上代码的学习,“super(实际参数列表);”语法表示调用父类的构造方法,代码复用性增强了 另外一方面也是模拟现实世界当中的“要想有儿子,必须先有父亲”的道理。

不过这里的“super(实际参数列表)”在调用父类构造方法的时候,从本质上来说并不是创建一个“ 立的父类对象”,而是为了完成当前对象的父类型特征的初始化操作。(或者说通过子类的构造方法 调用父类的构造方法,是为了让张小明身上长出具有他父亲特点的鼻子和眼睛,鼻子和眼睛初始化完毕之后,具有父亲的特点,但最终还是长在张小明的身上)。

接下来,再来看一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
css复制代码public class A{
public A(){
System.out.println("A 类的无参数构遗方法执行“;
}
}
public class B extends A{
public B(){
System.out.println("B 类的无参数构造方法执行");
}
}
public class C extends B{
public C(){
System.out.,printiln("C类的无参数构造方法执行");
}
}
public class Test {
public static void main(String[] args){
new C();
}
}
//程序运行结果如下:
A类的无参构造方法执行
B类的无参构造方法执行
C类的无参构造方法执行

通过以上内容的学习,super()的作用主要有以下两点:

  • 1,调用父类的构造方法,使用这个构造方法来给当前子类对象初始化父类型特征;
  • 2,代码复用

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%