关于this和super的区别(转载)

来源:互联网 发布:flash cs6软件下载 编辑:程序博客网 时间:2024/05/17 06:45
 
先看下面一段代码,比较短,

//父类
class FatherClass {
    public int value;
    public void f() {
        this.run();//注意这儿的是this,注意
    }
    public void run(){
        System.out.println("FatherClass.run():"+this.value);
    }
}

//子类
class ChildClass extends FatherClass {
    public int value = 100;
    public void ff() {
        super.run();//注意这儿的是super,注意
    }
    //重写
    public void run(){
        System.out.println("ChildClass.run():"+super.value); 字串6
    }
}

//孙子类,这儿用了一个拼音,偷懒一下,记不到那个孙子的单词了。寒啊...当初还过四级,现在忘光光
class SunziClass extends ChildClass {
    public int value = 200;
    //再次重写
    public void run() {
        System.out.println("SunziClass.run():"+super.value);
    }
}

//这儿是调用的Main
public class TestInherit {
      public static void main(String[] args) {
                FatherClass fc = new ChildClass();
                fc.f();
                FatherClass fc1 = new SunziClass();
                fc1.f();
字串1

                ChildClass cc = new SunziClass();
                cc.ff();
     }
}

想一想运行结果,注意那个this和super。有点晕头把,不要晕,稳住!自己想一下结果,然后再来看运行结果。

运行结果如下:
ChildClass.run():0;
SunziClass.run():100;
FatherClass.run():0;

估计有不少人会大吃一惊!其他不吃惊的人可以散了!吃惊的人继续看下面的。

this代表什么?这儿代表New出来的那个玩意儿在堆空间的引用地址
对于下面的这一句:
FatherClass fc1 = new SunziClass();
fc1这个变量里面放的就是this,是new SunziClass()这个玩意儿在堆空间的引用地址.
只是这儿fc1是定义成FatherClass,只有FatherClass的属性和方法是可见的,不过这不是本文讨论的重点.

所以说在父类里面写的this其实就是这个父类或者他的子类,孙子类,曾孙子类... 在运行的时候[重复一次哈,运行的时候runtime], New 子类()或者New 孙子类()或者New 曾子类()或者....的堆空间的引用地址.

字串4


[再重复一次,FatherClass里面的this,子类里面的this...都是一样的,指向New出来的那玩意儿的引用地址]

很神奇哈!!嘿嘿,这个其实就是多态的体现,也是多态的实现基础.看父类或者接口定义了方法调用的逻辑,子类可以根据需要改变算法!这样就可以将关注的方面分为两个层面,一:关注方法调用的业务逻辑[做什么],二:关注方法的实现[怎么做].  "做什么和怎么做",这玩意儿好像在软件工程里面比较眼熟哦!!!!

问题分解了,而且可复用性也大大提高了.

好了,this总结完了,好像越说越晕了... 再稳一下,看看Super

下面再来说super
说之前,分析一下内存多,这个图,挖卡,蜘蛛网来也....


字串2



现在看这两句:
ChildClass cc = new SunziClass();
cc.ff();
这儿SunziClass里面没有重写父类ChildClass的ff方法,
所以是执行的父类ChildClass的ff方法.这个方法里面有一个super.Run();
这儿实际上就执行到了FatherClass的Run()方法.

这说明什么啦.
说明super只是记录对象内部的父类的特征(属性和方法)的一个引用
(注意哈:这儿super不是指向父类对象的引用地址哈,new出来的玩意儿才在堆里面分配空间有引用地址,这儿没有去new一个父类对象哈,只是执行了父类的构造函数将父类的特征生成了,但是属于New出来的那个子类对象)
估计上面这段话也够晕人了...

实践一下,你可以写
public FatherClass getThis()
{
    return this;
}
编译通过,没有任何问题
但是你写
public FatherClass getSuper()
{
    return super; 字串3
}

嘿嘿,编译出错! 为什么啦,
因为super并不是一个堆空间里面的一个对象的引用地址,而this才是堆空间里面的一个对象的引用地址
    super只能在对象内部使用,而this可以在对象内部使用也可以返回出对象外.
    super是死的,编译的时候就定死了super的指向了,而this是活的,在运行时候决定其指向.

再说一下,子类实例化对象,并没有去实例化他的父类对象,也就是说,那个子类对象里面并没有一个父类对象,
那你说没有父类对象,为什么子类构造函数要执行父类的构造函数啦,那是因为需要创建父类的特征赋予子类,但是是由子类所有,而super就是用来区别是是否是父类对象的特征的.
重写父类方法属性,就是再创建了一个子类的特征,当你用this的时候,就覆盖了父类的特征了,但是父类特征还在那儿,用super就能访问道,但是只能在对象的内部使用.对象外面就只能看到覆盖了父类特征的子类特征了.

字串1



其实就是一句:"this是当前对象在堆空间的引用地址,super是当前对象的父类特征的引用"
原创粉丝点击