多态-编译时类型和运行时类型
先看源代码
class BaseClass
{
int count = 5;
public void display()
{
System.out.println(this.count);
}
}
public class SubClass extends BaseClass
{
int count = 15;
public void display()
{
System.out.println(this.count);
}
public static void main(String[] args)
{
//父类引用指向子类对象
BaseClass bc = new SubClass(); //-----①
System.out.println(bc.count); //-----②
bc.display();
}
}
输出结果
为什么结果会是这样?
引入两个概念-编译时类型、运行时类型
明白引用变量有两个类型:编译时类型、运行时类型。那么他们之间有什么区别吗?
编译时类型
编译时类型:由声明该变量时使用的类型决定。
比如,看源代码的注释①中,
引用变量bc的类型为BaseClass,这是声明时的类型。由此,bc的编译时类型为BaseClass。
运行时类型
运行时类型:由实际赋给引用变量的对象的类型决定。
比如,看源代码的注释①中的new SubClass(),
可见构造器创建的对象的类型是SubClass,显然后者是程序实际运行时的类型。
多态现象产生的条件
可以看到BaseClass bc = new SubClass()中“=”左边和右边的类型不一致,产生了源代码输出的结果。
由此,得出结论:
如果编译时类型和运行时类型不一致,就会出现多态。
通过源代码也有以下结论:
如果子类重写了父类的方法,那么就会覆盖父类中被重写的方法,这时,指向子类对象的引用调用这些父子类都有的方法无论声明时类型是其父类还是自身,调用的都是子类中重写后的方法,这叫做覆盖。而父类的成员变量却不会被子类中同名的成员变量所覆盖,当这些同名的实例变量被引用变量访问时,其返回值取决于引用的声明时类型。
作者:xuejingfu1
来源:CSDN
原文:https://blog.csdn.net/xuejingfu1/article/details/51497481
对于对象的实例变量,
对象的实例变量则不具备多态性。
来源:《疯狂Java讲义》
所以,我们看到源代码注释②中的bc.count使用的是父类对象的实例变量count,而不是子类对象的实例变量。
最后,需要特别注意的是,如果我们在声明一个引用变量后,又给这个引用变量赋值,这时候我们需要观察赋值的对象和这个引用变量之间是不是父子类的关系。如果是,注意有哪些地方使用了成员变量,哪些地方使用了成员方法,然后结合编译时类型和运行时类型不一致时,分析成员方法和变量的输出结果。