父类引用指向子类对象的注意点
首先看一段代码:
Father类
package JavaSE.lu.duotai;
public class Father {
static int b=7;
int a=5;
public void say(){
System.out.println("父亲say");
}
public void write(){
System.out.println("父亲write");
}
}
Son类
package JavaSE.lu.duotai;
public class Son extends Father {
static int b=9;
int a=4;
public void say(){
System.out.println("儿子say");
}
public void play(){
System.out.println("儿子play");
}
}
测试类
package JavaSE.lu.duotai;
public class Father_son {
public static void main(String[] args) {
Father father=new Son(); //父类引用开始指向子类.
father.say(); //输出:儿子say
father.write(); //输出:父亲write
// father.play();
System.out.println(father.a);
System.out.println(father.b);
Son son=new Son(); //正常引用儿子引用指向儿子
System.out.println(son.a);
System.out.println(son.b);
}
}
输出结果:
结果说明:
如果是父类引用指向子类对象这种形式,有以下几种情况:****
-
如果子类重写了父类的某个方法,那么此时调用的是子类重写的方法
-
如果子类没有重写父类的某个方法,那么此时调用的是父类中的方法
-
如果子类新增了父类中不存在的方法,那么这个父类引用是不能调用这个仅在子类中存在的方法中,因为子类对象自动向上转型为了父类对象
-
如果子类与父类有同名的成员变量和静态变量,那么由于子类自动向上转型为父类对象,此时调用father.a,那么输出的必然是父类的成员变量和静态变量,这里不存在子类覆盖父类同名变量这一说,因为这里本身可以看做是一个父类对象
-
如果是Son son=new Son(),那么这就是实实在在的一个子类对象,那么son.a和son.b,这样就会覆盖父类的同名变量,输出的是子类的成员变量a和静态成员变量b,如果子类中没有同名变量,那么son.a和son.b调用的是父类的a和b。换句话说,也就是子类可以继承父类的成员变量和静态变量,同时可以覆盖父类的成员变量和静态变量。
-
另外需要注意的是当父类中的某个方法是static的时候,如果同名那么子类也应该是static方法,但这种并不属于重写父类中的方法。在遇到父类引用指向子类对象的时候就会出现和之前不一样的结果。比如有父类Animal类和子类Dog类,当出现Animal a = new Dog(),语句a.eat()实际上调用的是父类方法。看以下示例代码:
测试类
public class Application {
public static void main(String[] args) {
Animal ason = new Dog();
ason.eat();
Dog dog = new Dog();
dog.eat();
}
}
Animal类
class Animal{
public static void eat(){
System.out.println("father:eat");
}
}
Dog类继承Animal类
class Dog extends Animal{
public static void eat(){
System.out.println("son:eat");
}
}
输出结果:
father:eat
son:eat
可以看出如果是static方法的时候,父类引用就只能调用父类的这个static方法。