你第一次遇到super关键字是什么时候呢?是不是使用IDEA或者eclipse快捷键生成类构造方法的时候出现在构造方法第一行的super()语句呢?在没有了解super关键字之前,相信你是很疑惑这行代码的作用的,没关系,本文带你全面详解super关键字,你就会知道这行代码有什么作用了(偷偷告诉你,实际上没有什么用,因为就算没有这一行代码JVM也会默认自动调用的)
我们将super关键字与this关键字对比来介绍,因为两者有许多相似之处:
1.this只能出现在构造方法和实例方法(不带staric关键字的方法)之中,代表的是当前正在调用这个方法的对象
2.super也只能出现在构造方法和实例方法中,代表的是当前对象的父类型特征
注意:怎么去理解这个父类型特征呢?
- super关键字代表的就是“当前对象”的那部分父类型特征。
比如: 我继承了我父亲的一部分特征 例如:眼睛、皮肤等
那么super代表的就是“眼睛、皮肤等”,“眼睛、皮肤等”
虽然是继承了父亲的,但这部分是长在我身上的。
1.super的第一种语法是:“super(实参列表)”
这种语法的作用是:通过子类的构造方法去调用父类的构造方法,用来给当前子类的父类型特征初始化值。
注意:
1.这里的父类型特征指的是从父类继承过来的那部分属性或者行为
2.虽然调用了父类的构造方法,但是并没有在底层创建父类对象,只是给当前子类对象的父类型特征赋了值,实际上对象只有当前子类对象一个
3.super(实参列表)只能出现在子类构造方法的第一行
4.super(),括号里没有参数代表调用父类的无参数构造方法
5.因为需要模拟现实世界中有父母才会有儿子的这种关系,所以java有一条语法就是:
子类的构造方法中第一行如果没有super(),也会默认有一个super(),表示通过子类构造方法去调用父类的无参构造方法,所以还必须保证父类的无参构造方法一定存在。
解释一下前言所提出的问题:
我们知道java中有一个超级父类Object类,所有引用数据类型都是Object的子类,
包括自己自定义的类也会默认继承Object,所以当你使用快捷键生成一个类的构
造方法的时候,会默认在构造方法第一行出现super()代码,你将这一行代码删除
了也没事,因为会默认有这一行代码。
举例代码如下:
public class Super {
public static void main(String[] args) {
Son son = new Son("张三",18,"华为");
System.out.println(son.name);
System.out.println(son.age);
System.out.println(son.phoneName);
}
}
/**
* 父亲类:Parent
* 说明:
* 1.属性有:姓名、年龄、手机名
* 2.方法有:构造方法
*/
class Parent{
String name;//姓名
int age;//年龄
String phoneName;//手机名
//无参构造
public Parent() {}
//有参构造
public Parent(String name, int age, String phoneName) {
this.name = name;
this.age = age;
this.phoneName = phoneName;
}
}
/**
* 儿子类:Son 继承父亲类
* 说明:属性和方法都继承于父亲,也就是说,此时的Son所有属性和方法都是“父类型特征”
*/
class Son extends Parent{
//子类Son的有参构造
public Son(String name,int age,String phoneName) {
//调用super(实参列表)调用父类的有参构造
//给当前子类的父类型特征初始化值,其实也就是子类自己的属性
//只不过是调用了父类的构造方法来初始化值
super(name, age, phoneName);
}
}
2.super的第二种语法是:“super.成员变量” 或者“super.成员方法”
这种语法的作用是:区分子类和父类中相同名字的成员变量或者相同名字的成员方法。
举例如下:假设有父亲类和儿子类,让儿子类去继承父亲类,儿子类和父亲类的属性和方法都相同,如何通过儿子类去访问继承自父亲的那部分特征呢,只有调用super关键字来区分,代码如下。
public class Super {
public static void main(String[] args) {
//创建一个儿子对象
//注意:传入的参数赋值给了子类自身的属性,子类继承的父类型特征默认给了值: super("张三",50,"oppo");
Son son = new Son("小小小张三",18,"华为手机");
//此时调用son的访问父类型特征方法
son.getParentData();
}
}
/**
* 父亲类:Parent
* 说明:
* 1.属性有:姓名、年龄、手机名
* 2.方法有:构造方法、玩手机方法
*/
class Parent{
String name;//姓名
int age;//年龄
String phoneName;//手机名
//无参构造
public Parent() {}
//有参构造
public Parent(String name, int age, String phoneName) {
this.name = name;
this.age = age;
this.phoneName = phoneName;
}
//玩手机方法
public void playPhone(){
System.out.println("父亲在玩手机!");
}
}
/**
* 儿子类:Son 继承父亲类
* 1.属性有:姓名、年龄、手机名
* 2.方法有:构造方法、玩手机方法、访问父类型特征方法
*/
class Son extends Parent{
String name;//姓名
int age;//年龄
String phoneName;//手机名
//无参构造
public Son() {}
//有参构造
public Son(String name, int age, String phoneName) {
//通过子类给从父亲继承过来的父类型特征赋值
super("张三",50,"oppo");
//给子类自己的属性赋值
//注意:子类中的name等属性和方法 与 父类中的name等属性和方法 是不同的
this.name = name;
this.age = age;
this.phoneName = phoneName;
}
//设计一个访问父类型特征的方法
public void getParentData(){
//如果以下属性和方法都不加super关键字,那么就是调用子类自身的属性和方法
System.out.println("父类型特征的name:" + super.name);
System.out.println("父类型特征的age:" + super.age);
System.out.println("父类型特征的phoneName:" + super.phoneName);
//父类型特征的玩手机方法
super.playPhone();
}
//玩手机方法
public void playPhone() {
System.out.println("儿子在玩手机!");
}
}
还是以上边提出的父亲类和儿子类为例:
注意:子类中调用super()父类的构造方法,父类的构造方法还会继续调用它的父类的super()构造方法,但是实际上对象只创建了一个。所有调用的super()构造方法只是在子类对象在JVM堆区中的那一块空间中占用一小部分来给父类型特征初始化值。
1.super只能出现在构造方法和实例方法
2.super有两种语法
1)super.成员属性 或者 super.实例方法
作用:调用那部分父类型特征的属性或者方法(大多时候可以省略)
2)super(实参列表)
作用:通过子类构造方法去初始化从父类继承过来的那部分父类型特征
3.super是一个对象级的关键字,也就是说得有对象才能调用super,所以super不能出现在静态方法中(带有static关键字的方法)
4.当访问的子类属性与父类继承过来的属性或方法名字不一样时,super关键字可以省略不写
5.当访问的子类属性与父类继承过来的属性或方法名字一样时,你又想要访问父类型的这部分特征时,必须使用super关键字
6.super(实参列表)只能出现在构造方法第一行
7.如果构造方法第一行没有super(),默认第一行有super(),只是你看不到