Super关键字

!!! note 目录

super关键字

  • 在Java中,this代表的是当前对象,super代表的是当前对象中的父亲特征。
  • super不能使用在静态上下文中。
  • 在构造方法中调用父类构造方法或者父类和子类中存在同名实例变量、实例方法时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
package com.camellia.oop24;

//父类
public class Person {

String name;
int age;
String email;
String address;

public Person() {
super();
}

Getter();
Setter(); //省略

// 实例方法

public void doSome(){
System.out.println("人类正在做一些事情!");
}
}

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
package com.camellia.oop24;

// 子类

public class Teacher extends Person{

//特有的属性:工资
double sal;

public Teacher() {
}

public Teacher(String name, int age, String email, String address, double sal) {
this.name = name;
this.age = age;
this.email = email;
this.address = address;
this.sal = sal;
}

Setter();
Getter();

public void display() {

System.out.println("姓名:" + this.name);
System.out.println("年龄:" + this.age);
System.out.println("邮箱:" + this.email);
System.out.println("住址:" + this.address);
System.out.println("工资:" + this.sal);
}
}

二、super不能缺省的几种情况

  • 如果父类和子类中存在同名的实例变量,为了明确指定使用父类的实例变量,必须使用 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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.camellia.oop24;
//父类同上。
//子类
public class Teacher extends Person{

//特有的属性:工资
double sal;
//name属性和父类属性同名。
String name;

public Teacher() {
}

public Teacher(String name, int age, String email, String address, double sal) {
//子类构造方法不写super也会调用父类无参构造,因为隐式调用了super();
this.name = name;
this.age = age;
this.email = email;
this.address = address;
this.sal = sal;
//父类name为null。
}

public double getSal() {
return sal;
}

public void setSal(double sal) {
this.sal = sal;
}

public void display() {

System.out.println("姓名:" + super.name);
System.out.println("年龄:" + super.age);
System.out.println("邮箱:" + super.email);
System.out.println("住址:" + super.address);
System.out.println("工资:" + this.sal);

System.out.println("姓名:" + this.name);
System.out.println("年龄:" + this.age);
System.out.println("邮箱:" + this.email);
System.out.println("住址:" + this.address);
System.out.println("工资:" + this.sal);
}

@Override
public void doSome() {
// 重写的要求:要求在父类方法的执行基础之上额外再添加一些代码。
System.out.println("do some开始执行了");
// super. 什么时候不能省略?父中有,子中有相同的,但是想在子类中访问父的,必须添加 super.
super.doSome();
System.out.println("do some方法执行结束了");

// this本身是一个引用。所以可以直接输出。
System.out.println(this);
// super本身不是一个引用。super只是代表了当前对象的父类型特征那部分,况且super能输出,是输出它父类,还是父类的父类?
// super 不能够单独的输出。
//System.out.println(super); // 编译报错。
}
}
  • 在子类构造方法中调用父类构造方法要使用super
    • 在子类构造方法中调用父类构造方法时,必须放在子类构造方法的第一行,否则编译器会报错。这是因为在创建子类对象时,首先需要初始化父类的部分。
    • 如果子类的构造方法没有显式地调用super(参数),也没有显示的调用this(参数),Java 编译器会默认插入对父类无参构造方法的调用,若父类没有无参则报错。
      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
      class Parent {
      private int x;

      // 父类构造方法
      Parent(int x) {
      this.x = x;
      System.out.println("Parent class constructor");
      }
      }

      class Child extends Parent {
      private int y;

      // 子类构造方法
      Child(int x, int y) {
      super(x);
      // 调用父类构造方法,必须放在子类构造方法的第一行,好处是增加代码复用。
      // 通过子类构造方法调用父类构造方法是为了给继承过来的父类型特征初始化。
      this.y = y;
      System.out.println("Child class constructor");
      }

      }

      public class Main {
      public static void main(String[] args) {
      Child child = new Child(10, 20);
      }
      }

注意:
在我们定义了有参构造方法后,尽量再定义无参构造方法以避免以上错误。