大聪明教你学Java | 深入浅出聊 super 关键字

6,739 阅读4分钟

前言

今天没有前言,都是干货硬货,这一篇文章肯定让你明白 super 的用法!废话不多说,咱们直接进入正题。

super()的使用

子类重写父类方法

/**
 * 父类
 * @description: father
 * @author: 庄霸.liziye
 * @create: 2021-12-06 15:05
 **/
public class father {

    private String fatherName = "小头爸爸";

    public void getName() {
        System.out.println("我是" + fatherName);
    }
}
/**
 * 子类
 * @description: son
 * @author: 庄霸.liziye
 * @create: 2021-12-06 15:07
 **/
public class son extends father{

    private String sonName = "大头儿子";

    @Override
    public void getName() {
        System.out.println("我是" + sonName);
        super.getName();
    }

    public static void main(String[] args) {
        father b = new father();
        b.getName();
    }
}

咱们运行一下代码,结果如👇 在这里插入图片描述 在子类中重写了父类的 getName() 方法,如果在重写的 getName() 方法中去调用父类的相同方法,就必须要通过 super 关键字去指明。

肯定会有一些小伙伴“另辟蹊径”,就不用 super 去指明,那么按照子类优先的原则,相当于还是在调用子类中的 getName() 方法,也就形成了死循环。咱们看看不用 super 关键字去指明会有什么情况发生~ 👇 在这里插入图片描述

子类重写父类变量

/**
 * 父类
 * @description: father
 * @author: 庄霸.liziye
 * @create: 2021-12-06 15:05
 **/
public class father {

    String name = "小头爸爸";
    
}
/**
 * 子类
 * @description: son
 * @author: 庄霸.liziye
 * @create: 2021-12-06 15:07
 **/
public class son extends father{

    String name = "大头儿子";

    public void getName() {
        System.out.println("我是" + name);
        System.out.println("我是" + super.name);
    }

    public static void main(String[] args) {
        son s = new son();
        s.getName();
    }
}

咱们运行一下代码,结果如👇 在这里插入图片描述 此时子类中有一个和父类一样的字段 name(也可以说成父类字段被隐藏了),为了获得父类的这个字段我们就必须加上super,如果还想玩花里胡哨的不加 super ,这时候肯定不会报错,因为此时都是访问的子类里面的字段,但是也就没什么意义了。

有些眼尖的小伙伴发现我们去掉了 private ,因为我们通过 super 关键字是不能访问父类中被 private 修饰的变量和方法,被 private 修饰的变量和方法属于父类的内部成员,其他对象是不能访问其 private 成员的。

子类构造方法中使用super

编译器会自动在子类构造方法的第一句加上 super 来调用父类的无参构造方法,此时 super 可以省略不写,如果写上的话必须在子类构造方法的第一句;当然也可以通过 super 来调用父类其他的构造方法,只要相应的把参数传过去就好。

/**
 * 父类
 * @description: father
 * @author: 庄霸.liziye
 * @create: 2021-12-06 15:05
 **/
public class father {

    public father(String name) {
        System.out.println("这是father类带参构造方法,名字是:"+name);
    }

}

/**
 * 子类
 * @description: son
 * @author: 庄霸.liziye
 * @create: 2021-12-06 15:07
 **/
public class son extends father{

    public son(String name) {
        super(name);
    }

    public static void main(String[] args) {
        new son("大头儿子和小头爸爸");
    }
}

咱们运行一下代码,结果如👇 在这里插入图片描述 在子类构造方法中使用 super 关键字时需要注意以下两点:

① 注意一

/**
 * 父类
 * @description: father
 * @author: 庄霸.liziye
 * @create: 2021-12-06 15:05
 **/
public class father {

    public father(String s) {

    }

}

在这里插入图片描述 如果一个类中没有写任何的构造方法,JVM会默认生成一个的无参构造方法。在继承关系中,由于在子类的构造方法中,第一条语句默认为调用父类的无参构造方法(即默认为super(),一般这句话省略了),所以当父类中定义了有参构造方法,而没有定义无参构造方法时,IDE会强制要求我们定义一个相同参数类型的构造方法。

② 注意二

/**
 * 父类
 * @description: father
 * @author: 庄霸.liziye
 * @create: 2021-12-06 15:05
 **/
public class father {

    public father(String s) {

    }

}

在这里插入图片描述 虽然我们在子类中自己定义了一个构造方法,但是在这个构造方法中还是默认调用了super(),但是父类中并不存在该构造方法,所以就出现编译错误了。

总结起来就是一句话:在子类的构造方法中,只要没有写明通过 super 去调用父类的某个构造方法,默认调用的都是无参构造方法,所以一定要确保父类中有相应的构造方法。

小结

本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇‍

希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)

如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。

爱你所爱 行你所行 听从你心 无问东西