关于Java编译时和运行时的差异

时间:2021-01-08 03:54:36
关于Java编译时和运行时的差异 //有兴趣的人,试试自己的基础,看看这个程序输出的是什么?//第一次解析,难免有点错漏,欢迎阅读者能指出我的错误,并与我分享,大家共同进步! 本人语文水平not good, 错别字就不说了 。。
//关注本人CSDN博客:http://my.csdn.net/erix1991
class Base {    private int a = 2;    public Base() {    this.display();         }public void display() {    System.out.println(a);    }}
class Derived extends Base {    private int a = 22;    public Derived() {    //super();    a = 222;}public void display() {    System.out.println(a);    }}

public class TestO {public static void main(String[] args) {new Derived();}}




//输出的是什么?  2, 22, 222?  都是错,答案输出的是0;   这是为什么? 
        首先明白一点,子类继承父类,如果有多个同名的实例变量,但是子类的同名实例并不能覆盖父类的实例变量 而且子类在堆空间里面分配两个 a实例的变量,而不是一个!       对于Java的构造函数,很多人都吧它理解成Java的对象都是通过构造函数来创建,其实这是错的,其实Java的构造函数只负责做一件事,就是执行对象的实例变量进行初始化!
       在类被虚拟机加载到虚拟机里的时候,对象所占的内存已经被分配下来了,对于基本类型的变量是0或者是false; 对于引用类型的变量,默认的就是null;
      我们再来看看这个程序执行的顺序吧。
        1,首先Derived 这个类被加载到虚拟机,主函数执行new Derived()在堆内存分配空间,因为Derived 继承与Base,那么内存里应该有两份a的实例变量,它们的默认值都是0
        2,Derived子类执行构造函数初始化,我们知道,子类初始化,必先执行父类的构造函数,这个程序里隐含了super()的父类构造函数在子类的构造函数里        3,执行super(),调用父类的构造函数,此时执行this.display(),那么这个this指向的是什么呢? 答案是Derived! 为什么不是Base;因为这个父类的构造函数时通过Derived对象来调用,那么这个this当然是Derived的!
       4,那么执行this.display()那么当然输出的是0里,因为Derived的a 还没有来的及初始化,在内存空间的默认值还是0;              那么需要解析的是,在Java里,当变量的编译时和运行时类型是不同的,系统在调用它的实例变量和实例方法时存在上述的差异, 就这个程序来说,在父类里,编译的时候,this.display(),这个this是父类,但是当运行的时候,那么this就变成子类的引用了