`
woodenfish
  • 浏览: 5603 次
社区版块
存档分类
最新评论

覆盖了父类的成员变量引发的问题

    博客分类:
  • Java
阅读更多

    this代表什么呢?代表当前类的某个对象?请看下面这段代码:

package cn.com.wg.task01;
 
public class CallOrder {
   class Base {
      private int i = 2;
      public Base() {
         System.out.println(this);
         this.display();
      }
      public void display() {
         System.out.println("Base " +this.i);
      }
   }
 
   class Child extends Base {
      private int i = 22;
      public Child() {
         System.out.println(this);
         i = 222;
      }
      public void display() {
         System.out.println("Child " + i);
      }
   }
 
   public void init() {
      new Child();
   }
 
   public static void main(String[] args) {
      new CallOrder().init();
   }
}

输出结果是什么呢?

cn.com.wg.task01.CallOrder$Child@d0da1d8
Child 0
cn.com.wg.task01.CallOrder$Child@d0da1d8

 

此时,子类和父类构造函数的this代表同一个对象!!!this理解为代表调用该方法的那个对象更合适。

我们知道子类的构造函数会调用父类的构造函数(如果没有显示的调用,默认隐式调用无参的构造函数),所以在该程序中,父类的无参构造函数会在子类的构造函数中调用。因此,子类和父类构造函数的this代表同一个对象。

 

那么,输出的“Child 0”怎么解释呢?这里就牵涉到JVM的内存分配了。下面简单介绍。

当JVM遇到new关键字时,就会开始在内存中给对象分配空间。一个简单的java对象的在内存中包括三个部分:对象头、变量、填充区域。new结束后,变量域是初始化后的值(即boolean为false,char为'\0',其他基本类型为0,对象为null)。当遇到new后的类名是才开始执行我们代码中的构造函数。

 

这是用javap看到的class文件中Child的构造函数内容:

 


 

这是Base类的构造函数:

在Base类的构造函数中调用display方法,显然是调用在Child里写的display方法,i也是Child里的i。但是Child中,i的初始化是在调用display之前完成的,所以此时i=0;

 

如果我们把Child里的display去除,会输出什么呢?“Base 2”。此时调用的display肯定是Base里的了,而且i的初始化在调用display之前,而且这个i是在Base中声明的。那么,问题来了,Child对象中有几个i变量呢?“2个”。

 

 

这些问题全是由子类中覆盖了父类的成员变量造成的,所以不要轻易覆盖父类的成员变量,而且很少一定要这么做

 

 

  • 大小: 59.5 KB
  • 大小: 10.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics