Java进阶学习笔记10——子类构造器

子类构造器的特点:

子类的全部构造器,都会先调用父类的构造器,再执行自己。

子类会继承父类的数据,可能还会使用父类的数据。所以,子类初始化之前,一定先要完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认就是super();

java 复制代码
package cn.ensource.d14_extends_constructor;

class F{
    public F() {
        System.out.println("F类构造器执行了!");
    }
}

class Z extends F{
    public Z() {
        super();
        System.out.println("Z类无参构造器执行了!");
    }

    public Z(String name) {
        super();
        System.out.println("Z类有参构造器执行了!");
    }
}


public class Test {
    public static void main(String[] args) {
        // 目标:先认识子类构造器的特点,再掌握子类构造器的应用场景
        Z z1 = new Z();
        Z z2 = new Z("播妞");
    }
}

执行结果:

可见,不管是子类有参构造器,还是子类无参构造器,都是先调用父类构造器,然后再执行子类构造器。

其实,在子类构造器中,默认会有一个super()存在,不管你调用,还是不调用,都调用这个方法。

如果父类没有默认的无参数构造器呢?

java 复制代码
package cn.ensource.d14_extends_constructor;

class F{
    public F(String name, int age) {
        System.out.println("F类有参构造器执行了!");
    }
}

class Z extends F{
    public Z() {
        super("播妞", 20);    // 默认存在的
        System.out.println("Z类无参构造器执行了!");
    }

    public Z(String name) {
        super("播妞", 20);    // 默认存在的
        System.out.println("Z类有参构造器执行了!");
    }
}


public class Test {
    public static void main(String[] args) {
        // 目标:先认识子类构造器的特点,再掌握子类构造器的应用场景
        Z z1 = new Z();
        Z z2 = new Z("播妞");
    }
}

在子类的构造器中调用super()方法。

常见的应用场景:

为什么要这么干?有什么应用场景呢?

java 复制代码
package cn.ensource.d14_extends_constructor;



public class Test2 {
    public static void main(String[] args) {
        // 目标:搞清楚子类构造器为什么要调用父类构造器,有啥应用场景
        Teacher t = new Teacher("李四", 30, "Java");
        System.out.println(t.getName() + " " + t.getAge() + " " + t.getSkill());
    }
}

class Teacher extends People {
    private String skill;

    public Teacher(String name, int age, String skill) {
        super(name, age);    // 在子类构造器中调父类的有参构造器
        this.skill = skill;  // 为当前对象的skill进行赋值
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }
}

class People {
    private String name;
    private int age;

    public People() {
    }

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

在子类的构造器中调用super("播仔", 20)调用父类的有参构造器。

然后再在子类构造器中为当前对象(this)的skill进行赋值。

super:代表父类存储空间的标识。可以理解为父类对象的引用。

父类存储空间是在方法区中,如下图:

子类构造器可以通过调用父类构造器,把对象中包含父类这部分的数据先进行初始化赋值,再回来把对象里包含子类这部分的数据也进行初始化赋值。

然后t.getter方法,都是到子类和父类中调用相应的的getter方法。

补充知识:

this(...)调用兄弟构造器。

在任意类的构造器中,都可以通过this(...)去调用该类的其他构造器。

java 复制代码
package cn.ensource.d14_extends_constructor;

public class Test3 {
    public static void main(String[] args) {
        // 目标:掌握类的构造器中,通过this(...)调用兄弟构造器
        Student s1 = new Student("李四", 26, "家里蹲大学");

        // 需求:如果学生没有填写学校,那么学校默认就是黑马程序员
        Student s2 = new Student("张三", 38);

        System.out.println(s2.getName());
        System.out.println(s2.getAge());
        System.out.println(s2.getSchoolName());
    }
}

class Student {
    private String name;
    private int age;
    private String schoolName;

    public Student() {

    }

    public Student(String name, int age) {
//        this.name = name;
//        this.age = age;
//        this.schoolName = "黑马程序员";
        this(name, age, "黑马程序员");
    }

    public Student(String name, int age, String schoolName) {
        this.name = name;
        this.age = age;
        this.schoolName = schoolName;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
}

小知识点:

不能在构造器中即写this(...),又写super(...)。这样写是有问题的。

如果父类没有无参构造方法,只有带参构造方法。该怎么办?

1、在父类中提供一个无参构造方法;

2、通过使用super关键字去显示的调用父类的带参构造方法。

推荐是自己给出无参构造方法。

相关推荐
计算机毕设定制辅导-无忧学长2 分钟前
《基于物品协同过滤的闲置书换购微信小程序设计开发》
java·vue.js·spring boot·微信小程序·uniapp·闲置书换购微信小程序·物品协同过滤算法
Best_Liu~3 分钟前
SpringBoot全局日期格式化
java·spring boot·后端
少年的范儿13 分钟前
IntelliJ IDEA 配置 JDK 21 与 Maven 教程(Windows):开发环境配置与验证
java·jdk·maven·intellij idea
RuoyiOffice15 分钟前
SpringBoot3 + openGauss:RuoYi Office 登录、流程发布与用印填报适配实战
java·数据库·spring boot·opengauss·信创
Dwzun32 分钟前
基于SpringBoot3+Vue3的油莎豆种植管理系统
java·前端·vue.js·spring boot·后端·python·计算机网络
学长毕设9 小时前
基于SpringBoot的实验室资产管理系统
java·spring boot·后端
zzu123zsw10 小时前
从臃肿的模板调用到声明式契约:深入 UniHttp 动态代理与多渠道生命周期扩展
java·spring boot·microsoft·unihttp
源码集结号11 小时前
云诊所门诊系统源码,基于SpringBoot+Vue.js架构,支持多租户设计与Docker容器化部署
java·spring boot·源码·医院信息系统·门诊系统·诊所系统
论文复现现场12 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
啃瓜子的松鼠12 小时前
泛微OAe9-后端二开异步调用
java