在new子类对象的时候,一定会调用父类的构造方法,这点毋庸质疑了。
我知道因为子类包含父类的属性和方法。
但是在构造的时候,一定会先初始化父类,执行父类的构造方法。
有人说,是因为子类在初始化的时候可能需要父类的属性或方法。那么在内存这种情况是什么样的呢? 我曾调用过hashCode方法,发现子类的哈希码和在调用父类构造方法的时候的哈希码是一样的class Father {
  Father(){System.out.println(this.hashCode());}
}

class Children extends Father {
    public static void main(String[] args) {
         Children c = new Children();
System.out.println(c.hashCode());
}
}打印结果 23899971
         23899971
我现在把子类在构建对象的时候,想象成一个圆形,其中有个内圆是子类,而外圆是父类。没有父类而无法创建子类。
但是,我不明白其中的原理。如果调用父类构造方法的画,父类应该有个无引用的对象吧。子类创建的时候也有一个对象。那么这两个对象是如何合并的??就是这个原理有点晕乎乎。想弄明白!

解决方案 »

  1.   

    我个人的理解是:我觉得这里没有两个对象的概念,你的 Children c = new Children();
        System.out.println(c.hashCode());
    其实就只创建了一个对象然后,this也就是指定当前对象。既然是一个对象,那么他们的哈希肯定就是一样的继承关系只是在类型的组织上,方法或者属性字段的继承和合并,这里就是一个对象
      

  2.   

    你在父类的构造方法中也打印了this.hashCode(),你可能认为这是父类的哈希码,但不是,此时应该调用的是子类中的hashCode(),因为hashCode()方法是成员方法,没有对象时不可能存在(依赖于具体对象,而此时父类根本就没有,所以必须是子类当中的方法)。
      

  3.   

    首先注意多态现象,Father(){System.out.println(this.hashCode());}
        }
    这句话里调用的hashCode()就是子类的hashCode()方法,当然因为子类没有覆盖该方法,所以调用的是Object中定义的。你可以这样考虑,子类的成员=父类的成员+子类定义中的成员,因此,你可以把子类考虑成一个大圆,而父类是这个圆里的一个必不可少的部分。Children c = new Children();
    就创建了一个Children对象,所以不要去考虑什么对象合并的问题。有一个比较有意思的现象,像C++中,会考虑子对象中父类的数据组成一个父类的对象,并考虑它们之间的布局关系。典型的支持证据是,在C++中,构造子类对象时,如果在父类的构造函数中调用了一个虚方法,此时调用的就是父类定义的方法,不会发生多态现象。我感觉,C++可能是认为“在调用父类构造函数时就是在构造父类的对象”。
    而java不同,你在父类的构造方法中调用了一个在子类中被覆盖的方法,比如下面这个例子:
    class Father {    Father() {
            System.out.println(this.hashCode());
        }    @Override
        public int hashCode() {
            System.out.println("Father's hashcode is :"+"father".hashCode());
            return "father".hashCode();
        }}
    class Children extends Father {    public static void main(String[] args) {
            Children c = new Children();
            System.out.println(c.hashCode());
            System.out.println(System.identityHashCode(c));
        }    @Override
        public int hashCode() {
            System.out.println("Childern's hashcode is :"+"children".hashCode());
            return "childeren".hashCode();
        }
    }
    结果发现在父类的构造方法中调用的this.hashCode()是子类中定义的hashCode()方法。所以,你可以认为java的世界观就是,在构造子类的过程中,我们只创建了一个对象,这就是子类的对象,在此构造过程中,即使是在父类构造方法中调用的虚方法,也是子类的虚方法。当然,在构造方法中调用方法不是什么好习惯。其实,将Children c = new Children();
    这句话理解成3个步骤可能方便一些
    1.通过new操作符分配内存,进行对象的布局和默认初始化工作。注意此时给Children对象布局的时候就包含了从父类继承下来的东西,那已经是子类血液的一部分了。得到此对象的引用。
    2.调用初始化方法(构造方法),该方法中首先会调用父类的初始化方法。【构造方法只是执行一些语句,跟内存非配无关】
    3.将new操作得到的引用赋给c。
      

  4.   

    非常感谢ZangXT 细致的回答子类在构造对象时,调用了父类的构造方法,构造方法一定会产生一个对象,那么父类的这个对象哪去了?
      

  5.   

    When you create an object of the derived class, it contains within it 
    a subobject of the base class. This subobject is the same as if you had created an object of the 
    base class by itself. It’s just that from the outside, the subobject of the base class is wrapped 
    within the derived-class object.这是thinking in java中的一段话,希望对你有帮助。
    它说当你创建了一个子类的对象时,在里面包含了一个父类的subobject
      

  6.   

    楼主看看下面这个帖子吧,和你问的问题比较类似,大家已经充分讨论过了
    http://topic.csdn.net/u/20090714/15/0b28ab3e-4270-4760-8cca-e9655d660f22.html
      

  7.   

    分析了很到位,学习一下拉,又发现个C++和JAVA的不同点~~