由于子类不能继承父类的构造方法,因此,如果要调用父类的构造方法,可以使用 super 关键字。super 可以用来访问父类的构造方法、普通方法和属性。
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 + "未婚");
}
}
}
使用 super 访问父类中的成员与 this 关键字的使用相似,只不过它引用的是子类的父类,语法格式如下:
super.member
其中,member 是父类中的属性或方法。使用 super 访问父类的属性和方法时不用位于第一行。
子类中想使用被子类隐藏的成员变量或方法就可以使用关键字super。比如super.x、super.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;
this 指的是当前对象的引用,super 是当前对象的父对象的引用。下面先简单介绍一下 super 和 this 关键字的用法。
super 关键字的用法:
如果构造方法的第一行代码不是 this() 和 super(),则系统会默认添加 super()。
this 关键字的用法:
当局部变量和成员变量发生冲突时,使用this.
进行区分。
关于 Java super 和 this 关键字的异同,可简单总结为以下几条。
在 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);
}
}
我是动物,我的名字叫喵星人