子类构造器的特点:
子类的全部构造器,都会先调用父类的构造器,再执行自己。
子类会继承父类的数据,可能还会使用父类的数据。所以,子类初始化之前,一定先要完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认就是super();
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()存在,不管你调用,还是不调用,都调用这个方法。
如果父类没有默认的无参数构造器呢?
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()方法。
常见的应用场景:
为什么要这么干?有什么应用场景呢?
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(...)去调用该类的其他构造器。
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关键字去显示的调用父类的带参构造方法。
推荐是自己给出无参构造方法。