super引用
重点:在java中创建对象时,首先会先创建父类的对象,再创建本类的对象
Person p = new Person();
super:super表示为当前对象的父类对象的引用,不能在静态的代码块使用
--super和this一样,都表示为一个对象引用,所以不能在静态代码块中使用
--在构造器中super();写和不写都一样,因为系统会默认调用父类的无参构造器创建父类的对象
--super可以调用父类的构造器,必须要在构造器的第一行
--super可以调用父类的属性和方法
创建一个父类Person、一个子类Student和一个测试类Test
创建Student时 Student-->Person-->Object
/**
* @author Lantzrung
* @date 2022年7月21日
* @Description
*/
public class Student extends Person {
// 如何在子类中快速生成父类构造器 ecpilse中 ctrl+s快捷键找到即可完成 idea是 ait+ins
// Generate Constructors from Superclass;
// 意思就是:调用回父类的构造器
// 注意:本类在创建对象时,会先创建父类的对象 调用父类的无参构造器
// 注意:子类默认调用父类的无参构造器,所以要注意父类有无给无参构造器
// 注意:就算不在无参构造器中显示super();也会提供父类的无参构造器
public Student() {
// Constructor call must be the first statement in a constructor
// 构造函数调用必须是构造函数中的第一条语句
// System.out.println();
super();// 调用父类的无参构造器
}
// 注意:增加一个细节
// 要是我取消了父类当中的无参构造器就会出现报错找不到父类无参构造器
// public Student() {
// //The constructor Person() is undefined
// //构造函数Person()未定义
// super();
// }
public Student(String name, String sex, int age) {
super(name, sex, age);// 调用父类全参构造器
// 这里的属性是属于谁的?子类还是父类
// 详细解说: 现在这里是属于子类的局部变量(属性),然后它调用给对应的父类构造器中的局部变量,最终赋值给父类的成员变量。
}
public void eat() {
System.out.println("学生在饭堂吃饭");
}
// super表示为当前对象的父类对象的引用
// 操作二:定义一个方法来调用操作父类对象的引用
public void superEat() {
// eat();//java中默认调用的是本类的构造器,this.
// this.eat();// 它调用的还是学生吃饭行为
super.eat();
}
}
/**
* @author Lantzrung
* @date 2022年7月21日
* @Description
*/
public class Person {
public String name;
public String sex;
public int age;
public void eat() {
System.out.println("人吃饭的行为");
}
public Person(String name, String sex, int age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}
public Person() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]";
}
}
/**
* @author Lantzrung
* @date 2022年7月21日
* @Description
*/
import com.day0721.Student;
public class Test {
public static void main(String[] args) {
// // 调用父类引用变量指向子类的对象
// Person p = new Student();
// // 操作一:调用的是子类学生的吃饭行为
// p.eat();//学生在饭堂吃饭
// 操作二:我想要调用父类的引用方法无法直接调用eat方法
// super.eat();//错误不能直接调用
// Student s = new Student();
// s.superEat();//学生在饭堂吃饭 this.eat()这时候是调用学生吃饭的行为;
Student s = new Student();
s.superEat();// 人吃饭的行为 super.eat();这时候是调用父类吃饭的行为;
// zhangan --> Person 对象1
// lisi --> Person 对象2
}
}
这里的// zhangan --> Person 对象1
// lisi --> Person 对象2
插入一张图片方便理解
--父类的成员变量存放在父类的对象,而不是在子类的对象中;
父类还是按照上个Person不变
/**
* @author Lantzrung
* @date 2022年7月21日
* @Description
*/
public class Student extends Person {
public Student() {
super();
}
public Student(String name, String sex, int age) {
super(name, sex, age);
}
public void test() {
System.out.println(this.name + ":" + super.name);
}
}
/**
* @author Lantzrung
* @date 2022年7月21日
* @Description
*/
public class Test01 {
public static void main(String[] args) {
Student p = new Student("zhang","nan",18);
p.test();//zhang:zhang
//为什么输出都是zhang?
//因为子类对象中没有定义name,就只有父类中有定义
//所以默认调用的成员变量是父类的,子类的也是一样调用父类的name详细看图
Student p1 = new Student("li","nan",29);
p1.test();//li:li
}
}
--而子类中定义的成员变量,还是存放在子类的对象中
【成员变量没有多态、根据编译时类型来调用】
父类这里我偷懒一下 只要修改一下 name的数据即可,以上数据和之前父类一致
public class Person { public String name = "p_name"; }
/**
* @author Lantzrung
* @date 2022年7月21日
* @Description
*/
public class Student extends Person {
public String code;
public String name;
public void test() {
System.out.println(this.name + ":" + super.name);
}
public Student() {
super();
}
// public Student(String name, String sex, int age) {
// super(name, sex, age);//子类调用父类的全参构造器
// }
public Student(String name, String sex, int age) {//本类中的全参构造器
this.name = name;
this.sex = sex;
this.age = age;
}
}
/**
* @author Lantzrung
* @date 2022年7月21日
* @Description
*/
public class Test02 {
public static void main(String[] args) {
// Student p1 = new Student("zhang","nan",18);
// p1.code="001";
// p1.test();//zhang:zhang
// Student p2 = new Student("li","nan",30);
// p2.code="002";
// p2.test();//li:li
// System.out.println(p1.code);//001
// System.out.println(p2.code);//002
// 操作一:子类和父类都存在成员变量name;
// 子类的不是调用父类的全参构造器,而是使用本类中的全参构造器
// Student p1 = new Student("zhang","nan",18);
// p1.test();//zhang:null
// Student p2 = new Student("li","nan",30);
// p2.test();//li:null
// 为什么会输出为this.name会有zhang的数据而父类为null呢?
// 原因就是它使用的是本身的成员变量,而不是父类的成员变量,还有就是调用的是本类的全参构造器,
// 而没有使用到父类的调用的构造器故此父类里面的成员变量并没有给赋值到
// 操作二:子类和父类都存在成员变量name;
// 子类调用父类的全参构造器
// Student p1 = new Student("zhang", "nan", 18);
// p1.test();// null:zhang
// Student p2 = new Student("li", "nan", 30);
// p2.test();// null:li
// 为什么会输出为会父类有zhang的数据而this.name为null呢?
// 原因与操作一差不多
// 操作三:
// 把父类name进行赋值为p_name;子类使用本类的全参构造器
// Person p1 = new Student("zhang", "nan", 18);
// Person p2 = new Student("li", "nan", 30);
// System.out.println(p1.name);//p_name
// System.out.println(p2.name);//p_name
// 成员变量没有多态 根据编译时运行的
// 原因是因为子类调用的是本类的全参构造器,返回的数据和属性也是本类的
// 又因为编译时的调用的引用类型是父类的,而不是子类的故此输出的是p_name;
// 最重要的是成员变量没有多态,要是有多态那么输出的应该是zhang和li而不是两个p_name,这个自己思考一下即可
// 操作三、扩展
// 注意条件还是把父类name进行赋值为p_name;子类使用本类的全参构造器
// 但要是把前面的引用类型改为子类的就可输出子类的数据了
Student p1 = new Student("zhang", "nan", 18);
Person p2 = new Student("li", "nan", 30);
System.out.println(p1.name);// zhang
System.out.println(p2.name);// p_name
}
}
附图: