在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
我现在把子类在构建对象的时候,想象成一个圆形,其中有个内圆是子类,而外圆是父类。没有父类而无法创建子类。
但是,我不明白其中的原理。如果调用父类构造方法的画,父类应该有个无引用的对象吧。子类创建的时候也有一个对象。那么这两个对象是如何合并的??就是这个原理有点晕乎乎。想弄明白!
我知道因为子类包含父类的属性和方法。
但是在构造的时候,一定会先初始化父类,执行父类的构造方法。
有人说,是因为子类在初始化的时候可能需要父类的属性或方法。那么在内存这种情况是什么样的呢? 我曾调用过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
我现在把子类在构建对象的时候,想象成一个圆形,其中有个内圆是子类,而外圆是父类。没有父类而无法创建子类。
但是,我不明白其中的原理。如果调用父类构造方法的画,父类应该有个无引用的对象吧。子类创建的时候也有一个对象。那么这两个对象是如何合并的??就是这个原理有点晕乎乎。想弄明白!
System.out.println(c.hashCode());
其实就只创建了一个对象然后,this也就是指定当前对象。既然是一个对象,那么他们的哈希肯定就是一样的继承关系只是在类型的组织上,方法或者属性字段的继承和合并,这里就是一个对象
}
这句话里调用的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。
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
http://topic.csdn.net/u/20090714/15/0b28ab3e-4270-4760-8cca-e9655d660f22.html