Java中关键字 super表示的真正对象
java中的super,大家都知道是表示一个父类的引用。上次群里见到一个网友询问 super.getClass().getName()的输出问题,大部分都知道输出的是当前这个类的类名。而不是父类的名称。关于这个问题的解释很多,基本都是说getClass()是一个final方法,说这个方法都是调用超父类Object的方法。这个解释很好,也容易理解,不过,我们从super这个关键词的本质入手,就能更清楚,为什么super.getClass().getName()会输出当前类的名称了。
先定义两个类,一个父类,一个继承的子类。
父类:
- public class Parent {
- public String name;
- private int code;
- public Parent parent;
- //定义几个父类成员属性,parent将指向this父类对象
- public Parent()
- {
- //parent指向this,就是当前实例的父类对象,并输出hashcode和给code属性赋值
- parent=this;
- code=1001;
- 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=1002;
- System.out.println("Parent's code is"+code);
- System.out.println("Parent hashcode is:"+this.hashCode());
- }
- public int getCode()
- {
- //打印父类code属性值,
- 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 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("window");
- c.test();
- }
- }
运行结果:
- Parent's code is:1001
- Parent hashcode is:366712642
- child's childName is:window
- child hashcode is:366712642
- testChild name is:window
- Parent :print code :1001
- Parent's code is:1001
- //表示执行了父类默认的构造器。其实在子类的构造器中,只要没有显示调用this和super,都会默认调用父类无参构造器,即:super(); Parent
- hashcode is:366712642
- //这里是父类对象的哈希值
- child's childName is:window
- //调用子类的构造方法,输出childName和hashcode码值,大家可以看到,父类的this对象和子类实例的对象,hashcode码是相同的。
- child hashcode is:366712642
- * //这里执行test()方法的结果。
- //使用Child testChild=(Child)super.parent 强制转换父类中指向父类this对象的parent对象为子类Child对象,并输出子类childName属性值。
- testChild name is:window
- //输出结果上可以看出,这个parent其实就是子类的实例对象。应该说内存中的对象是同一个,只是不同的表示方式。
- //执行testChild.getCode(); 调用父类的getCode()方法,输出的和父类构造方法中的code值是相同的。
- Parent :print code :1001
从上面可以看出super这个关键字所表示的引用父类对象,其实和当前实例化的子类对象在内存中是同一个对象,虽然不知道sun 的虚拟机是如何实现这个关键字的,但是这个super的等同效果就是(Parent)this,这里的this是当前代表当前实例化的子类对象。
通过在父类中添加一个Parent类型的成员,来指向父类实例化的那个this对象,达到引用父类对象的目的,使用super.parent来获得父类parent对象的引用。
运行的结果表明,这个parent应用的其实就是当前子类实例对象,通过强制转换为子类类型,这个父类Parent类型的parent也可以读取成员childName属性值。就表明了他们在内存中是同一个对象。而且他们的hashcode值也是相同的。
java说明中指出,super是代表父类对象的引用,而super()表示应用父类的默认构造方法,看起来这个super和c中的define有点相同作用的效果。在这个例子中,super代表的父类对象的引用,和父类中parent代表的都是父类对象的引用,parent其实就是当前内存中子类对象的引用,如同(Parent)this一样,这样就可以解释为什么使用(Child)super.parent可以得到子类成员childName。
回到开始的问题,super.getClass().getName(),这样,就很容易解释他为什么是输出当前类的名称了,因为构造一个实例化对象,其中,在父类和子类构造方法中,引用的对象都是同一个,都是当前实例化的子类对象。super关键字应该充当了一个类型转化的作用。
熟悉c的知道,c中经常使用强制转换指针类型来引用一些结构或变量的部分数据,如通过强制转换为不同结构类型,来引用不同数据大小的结构体。这里的应用效果应该等同,通过(Parent)Child可以通过转换为父类类型而只引用父类类型的那一部分数据。
在java中new一个对象,和c或c++这些和内存打交道的语言一样,都是会分配内存,在c中可能更直观一点,我们在此不讨论到底是分配了多大的内存问题。
在new一个子类的时候,上面例子看到,父类的成员同样也有赋值初始化,说明,同样在内存中也有保存父类的信息空间,(Object类的不讨论)。
一个抽象点的图:
-----------------------------------------------------------------JacobGo!--------------------------------------------------------------------------
本文转载自:http://blog.csdn.net/sujudz/article/details/8034770