Java中super关键字介绍

由于子类不能继承父类的构造方法,因此,如果要调用父类的构造方法,可以使用 super 关键字。super 可以用来访问父类的构造方法、普通方法和属性。

super 关键字的功能:

  • 在子类的构造方法中显式的调用父类构造方法
  • 访问父类的成员方法和变量。

1、使用super调用父类的构造方法

super必须是子类构造方法中头一条语句

当我们在父类中定义多个构造方法时,应当包括一个不带参数的构造方法,以防子类省略super时出现错误

声明父类 Person 和子类 Student,在 Person 类中定义一个带有参数的构造方法,代码如下:

public class Person {
    public Person(String name) {

    }
}
public class Student extends Person {

}

会发现 Student 类出现编译错误,提示必须显式定义构造方法,错误信息如下:

Implicit super constructor Person() is undefined for default constructor. Must define an explicit constructor

在本例中 JVM 默认给 Student 类加了一个无参构造方法,而在这个方法中默认调用了 super(),但是 Person 类中并不存在该构造方法,所以会编译错误。

如果一个类中没有写任何的构造方法,JVM 会生成一个默认的无参构造方法。在继承关系中,由于在子类的构造方法中,第一条语句默认为调用父类的无参构造方法(即默认为 super(),一般这行代码省略了)。所以当在父类中定义了有参构造方法,但是没有定义无参构造方法时,编译器会强制要求我们定义一个相同参数类型的构造方法。 

子类 Student 继承了 Person 类,使用 super 语句来定义 Student 类的构造方法。示例代码如下:

public class Student extends Person {
    public Student(String name, int age, String birth) {
        super(name, age); // 调用父类中含有2个参数的构造方法
    }

    public Student(String name, int age, String sex, String birth) {
        super(name, age, sex); // 调用父类中含有3个参数的构造方法
    }
}

 从上述 Student 类构造方法代码可以看出,super 可以用来直接调用父类中的构造方法,使编写代码也更加简洁方便。
编译器会自动在子类构造方法的第一句加上super();来调用父类的无参构造方法,必须写在子类构造方法的第一句,也可以省略不写。通过 super 来调用父类其它构造方法时,只需要把相应的参数传过去。

public class Student 
{
	int number;
	String name;
	Student(){
	}
	Student(int number, String name){
		this.number = number;
		this.name = name;
	}
	public int getNumber(){
		return number;
	}
	public String getName(){
		return name;
	}
}
public class UniverStudent extends Student
{
	boolean isMarriage;   //子类新增的结婚属性
	UniverStudent(int number, String name, boolean b){
		super(number, name);
	}
	public boolean getIsMarriage(){
		return isMarriage;
	}
}
public class Example5_6 
{
	public static void main(String[] args) 
	{
		UniverStudent zhang = new UniverStudent(20111, "张三", false);
		int number = zhang.getNumber();
		String name = zhang.getName();
		boolean marriage = zhang.getIsMarriage();
		System.out.println(name + "的学号是:" + number);
		if(marriage == true){
			System.out.println(name + "已婚");
		}
		else{
			System.out.println(name + "未婚");
		}
	}
}

2、调用被隐藏的成员变量和方法

使用 super 访问父类中的成员与 this 关键字的使用相似,只不过它引用的是子类的父类,语法格式如下:

super.member

其中,member 是父类中的属性或方法。使用 super 访问父类的属性和方法时不用位于第一行。

子类中想使用被子类隐藏的成员变量或方法就可以使用关键字super。比如super.xsuper.play()就是访问和调用被子类隐藏的成员变量x和方法play()

super调用隐藏的方法时,该方法中出现的成员变量是指被隐藏的成员变量

public class Sum 
{
	int n;
	public double f(){
		double sum = 0;
		for(int i = 1; i<= n; i++){
			sum += i;
		}
		return sum;
	}
}
public class Average extends Sum 
{
	double n;  //子类继承的int型变量n被隐藏
	public double f(){
		double c;
		super.n = (int)n;  //double类型变量n做int转换,将结果赋给隐藏的int型变量n
		c = super.f();
		return c + n;
	}
	public double g(){
		double c;
		c = super.f();
		return c - n;
	}
}
public class Example5_7 
{
	public static void main(String[] args) 
	{
		Average aver = new Average();
		aver.n = 100.5678;
		double result1 = aver.f();
		double result2 = aver.g();
		System.out.println("result1 = " + result1);
		System.out.println("result2 = " + result2);
	}
}

如果改写成(颠倒顺序)

double result2 = aver.g();

double result1 = aver.f();

运行结果:

result1 = 5150.5678

result2 = -100.5678

因为执行“aver.g();”的过程中需要执行"super.f();",super.f()中出现的n是隐藏的n且n还没有赋值。默认为0;

3、super和this的区别

this 指的是当前对象的引用,super 是当前对象的父对象的引用。下面先简单介绍一下 super 和 this 关键字的用法。

super 关键字的用法:

  • super.父类属性名:调用父类中的属性
  • super.父类方法名:调用父类中的方法
  • super():调用父类的无参构造方法
  • super(参数):调用父类的有参构造方法

如果构造方法的第一行代码不是 this() 和 super(),则系统会默认添加 super()。


this 关键字的用法:

  • this.属性名:表示当前对象的属性
  • this.方法名(参数):表示调用当前对象的方法

当局部变量和成员变量发生冲突时,使用this.进行区分。

关于 Java super 和 this 关键字的异同,可简单总结为以下几条。

  1. 子类和父类中变量或方法名称相同时,用 super 关键字来访问。可以理解为 super 是指向自己父类对象的一个指针。在子类中调用父类的构造方法。
  2. this 是自身的一个对象,代表对象本身,可以理解为 this 是指向对象本身的一个指针。在同一个类中调用其它方法。
  3. this 和 super 不能同时出现在一个构造方法里面,因为 this 必然会调用其它的构造方法,其它的构造方法中肯定会有 super 语句的存在,所以在同一个构造方法里面有相同的语句,就失去了语句的意义,编译器也不会通过。
  4. this( ) 和 super( ) 都指的是对象,所以,均不可以在 static 环境中使用,包括 static 变量、static 方法和 static 语句块。
  5. 从本质上讲,this 是一个指向对象本身的指针, 然而 super 是一个 Java 关键字。

在 Animal 类和 Cat 类中分别定义了 public 类型的 name 属性和 private 类型的 name 属性,并且 Cat 类继承 Animal 类。那么,我们可以在 Cat 类中通过 super 关键字来访问父类 Animal 中的 name 属性,通过 this 关键字来访问本类中的 name 属性,如下面的代码:

// 父类Animal的定义
public class Animal {
    public String name; // 动物名字
}

//子类Cat的定义
public class Cat extends Animal {
    private String name; // 名字

    public Cat(String aname, String dname) {
        super.name = aname; // 通过super关键字来访问父类中的name属性
        this.name = dname; // 通过this关键字来访问本类中的name属性
    }

    public String toString() {
        return "我是" + super.name + ",我的名字叫" + this.name;
    }

    public static void main(String[] args) {
        Animal cat = new Cat("动物", "喵星人");
        System.out.println(cat);
    }
}
我是动物,我的名字叫喵星人

猜你喜欢

转载自blog.csdn.net/qq_43629083/article/details/108673552