很早前就看过继承关系中的初始化顺序如下:
父类对象---》父类属性初始化---》父类构造方法(无参)----》子类对象----》子类属性初始化--》子类构造方法
这次来验证一下
父类:
public class Parent {
public String name;
private int code;
public Parent parent;
//定义几个父类成员属性,parent将指向this父类对象
public Parent()
{
//parent指向this,就是当前实例的父类对象,并输出hashcode和给code属性赋值
parent=this;
code=101;
System.out.println("调用了父类无参构造方法 Parent's code is:"+code);
System.out.println("Parent hashcode is:"+this.hashCode());
}
//定义一个重载的构造方法,用于测试使用了哪个父类构造方法
public Parent(String name){
parent=this;
this.name=name;
System.out.println("Parent's name is"+name);
code=102;
System.out.println("Parent's code is"+code);
System.out.println("Parent hashcode is:"+this.hashCode());
}
public int getCode()
{
System.out.println("Parent :print code :"+code);
return code;
}
}
子类:
public class Child extends Parent {
public String childName;
private int childCode;
public Child(String childName)
{
this.childName=childName;
//输出属性值,和类的hashcode值
System.out.println("child's childName is:"+childName);
System.out.println("child hashcode is:"+this.hashCode());
}
public Child(){
System.out.println("调用了子类无参构造方法 child hashcode is:"+this.hashCode());
}
//测试方法
public void test()
{
//通过super获取父类中的parent,这个成员就表示了父类对象。
Child testChild=(Child)super.parent;
//强转parent为子类类型。并输出子类中定义的属性,和获取父类getCode()方法
System.out.println("testChild name is:"+testChild.childName);
testChild.getCode();
}
public static void main(String[] args) {
//调用无参
Child c=new Child();
c.test();
//调用有参
Child d =new Child("hello");
d.test();
}
}
运行结果如下:
调用了父类无参构造方法 Parent's code is:101
Parent hashcode is:1163157884
调用了子类无参构造方法 child hashcode is:1163157884
testChild name is:null
Parent :print code :101
调用了父类无参构造方法 Parent's code is:101
Parent hashcode is:1956725890
child's childName is:hello
child hashcode is:1956725890
testChild name is:hello
Parent :print code :101
运行结果分析:
- 对于子类带参和无参的构造方法,先调用的都是父类的无参构造法。实际上,子类的构造方法必须先调用父类的构造方法,完了才能干别的初始化工作。如果子类没有显式调用语句,编译器会隐式帮你加上。
- 父类的this对象和子类实例的对象,hashcode码是相同的。从上面可以看出super这个关键字所表示的引用父类对象,其实和当前实例化的子类对象在内存中是同一个对象,虽然不知道sun 的虚拟机是如何实现这个关键字的,但是这个super的等同效果就是(Parent)this,这里的this是当前代表当前实例化的子类对象。
-
java说明中指出,super是代表父类对象的引用,而super()表示应用父类的默认构造方法,看起来这个super和c中的define有点相同作用的效果。在这个例子中,super代表的父类对象的引用,和父类中parent代表的都是父类对象的引用,parent其实就是当前内存中子类对象的引用,如同(Parent)this一样,这样就可以解释为什么使用(Child)super.parent可以得到子类成员childName。
回到开始的问题,super.getClass().getName(),这样,就很容易解释他为什么是输出当前类的名称了,因为构造一个实例化对象,其中,在父类和子类构造方法中,引用的对象都是同一个,都是当前实例化的子类对象。super关键字应该充当了一个类型转化的作用。
所以,可以理解为super等同于(超类)this,强制类型转换this引用为父类引用