当父类的对象引用没有指向父类的对象,而是指向了子类的对象时,调用方法或访问变量时会怎样呢?
假设父类为Person,子类为Student,有下面的两行定义:
Student sTest = new Student();
Person pTest = sTest;
其中,pTest就是父类的对象引用,sTest是子类的对象引用;pTest和sTest指向了同一个子类对象。
那么,
(1).如果子类的成员变量与父类的成员变量的类型及名称都相同,则用sTest访问时,访问到的是子类的成员变量;用pTest访问时,访问到的是父类的成员变量;
(2).如果子类的静态成员变量与父类的静态成员变量的类型及名称都相同,则用sTest访问时,访问到的是子类的静态成员变量;用pTest访问时,访问到的是父类的静态成员变量;
(3).如果子类的静态成员方法重写了父类的静态成员方法,则用sTest调用时,调用的是子类的静态成员方法;用pTest调用时,调用的是父类的静态成员方法;
(1)、(2)、(3)都称为隐藏,可以理解成父类的这些变量和静态成员方法被放到抽屉里暂时藏起来了,当用父类对象引用访问或调用时,把抽屉拉开就可以看到了;
(4).如果子类的成员方法重写了父类的成员方法,则用sTest调用时,调用到的是子类的成员方法;用pTest调用时,调用的也是子类的成员方法;
此时称为覆盖,可以理解成父类的这些方法被子类重写后的方法用胶带给粘上了,撕不下来了,即使父类对象引用调用时也只能看到子类重写后的方法;
(5).用sTest调用未覆盖的父类成员方法时,该方法中如果使用到了被隐藏的变量或方法时,规则同上;
还是以简单的示例来详细说明。
Person类为父类,Student类为子类,TestMain类为测试类。代码分别如下:
Person类的代码为:
package human; public class Person { String name; int age; String gender; public String education; private String hobby; protected String residence; static String citizenship = "Chinese"; public Person() { } public void setName(String n) { this.name = n; } public String getName() { return name; } public void informationPrint() { System.out.println("My name is(getName) " + getName()); System.out.println("My name is(name) " + name); System.out.println("I am " + getAge() + " years old"); if(getGender() == "female") System.out.println("I am a girl"); else if(getGender() == "male") System.out.println("I am a boy"); else System.out.println("Something is wrong!"); System.out.println("My hobby is " + hobby); if(citizenship == "Chinese") System.out.println("I am a chinese"); //test:静态变量是否在构造方法之前初始化 else if(citizenship == "US") System.out.println("I am an American"); else System.out.println("Oh,something is wrong"); } //test:覆盖 public void testModifierPublic() { System.out.println("Person:Public"); } //test:隐藏 public static void staMethodHide() { System.out.println("Person:static Method"); } }
Student类的代码为:
package human; public class Student extends Person { String stuNumber; int score; //test:隐藏 String name = "ha"; static String citizenship = "US"; public Student() { } public Student(String n, String g) { super(n,g); } //test:隐藏 public void setName(String n) { this.name = n; } //test:隐藏 public String getName() { return name; } //test:覆盖 public void testModifierPublic() { System.out.println("Student:Public"); } //test:super public void testSuper() { System.out.println("Super:"); super.testModifierPublic(); } //test:隐藏 public static void staMethodHide() { System.out.println("Student:static Method"); } }
TestMain类的代码为:
package human; public class TestMain { public static void main(String[] args) { Student sTest = new Student(); Person pTest = sTest; System.out.println("下面是以子类对象sTest来访问变量、调用方法的结果:"); sTest.testModifierPublic(); System.out.println(sTest.name); System.out.println(sTest.getName()); System.out.println(sTest.citizenship); sTest.staMethodHide(); sTest.testSuper(); sTest.informationPrint(); System.out.println("下面是以父类对象pTest来访问变量、调用方法的结果:"); pTest.testModifierPublic(); System.out.println(pTest.name); System.out.println(pTest.getName()); System.out.println(pTest.citizenship); pTest.staMethodHide(); } }
输出结果为:
1 下面是以子类对象sTest来访问变量、调用方法的结果: 2 Student:Public 3 ha 4 Student:getName() 5 ha 6 US 7 Student:static Method 8 Super: 9 Person:Public 10 Student:getName() 11 My name is(getName) ha 12 My name is(name) null 13 I am 0 years old 14 Something is wrong! 15 My hobby is null 16 I am a chinese 17 下面是以父类对象pTest来访问变量、调用方法的结果: 18 Student:Public 19 null 20 Student:getName() 21 ha 22 Chinese 23 Person:static Method