关于this和super又必要理解清楚的地方!重要的,多态的关键
二话不说,先来一段代码,比较短,需要付出一点点耐心(估计一上来就是代码,又会赶走很多人吧.....)
//父类
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);
}
}
//孙子类,这儿用了一个拼音,偷懒一下,记不到那个孙子的单词了。寒啊...当初还过四级,现在忘光光
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();
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 曾子类()或者....的堆空间的引用地址.
[再重复一次,FatherClass里面的this,子类里面的this...都是一样的,指向New出来的那玩意儿的引用地址]
很神奇哈!!嘿嘿,这个其实就是 多态的体现,也是多态的实现基础.看父类或者接口定义了方法调用的逻辑,子类可以根据需要改变算法! 这样就可以将关注的方面分为两个层面,一:关注方法调用的业务逻辑[做什么],二:关注方法的实现[怎么做]. "做什么和怎么做",这玩意儿好像在软件工程里面比较眼熟哦!!!!
问题分解了,而且可复用性也大大提高了.
好了,this总结完了,好像越说越晕了... 再稳一下,看看Super
下面再来说super
说之前,分析一下内存多,这个图,挖卡,蜘蛛网来也....
现在看这两句:
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;
}
嘿嘿,编译出错! 为什么啦,
因为super并不是一个堆空间里面的一个对象的引用地址,而this才是堆空间里面的一个对象的引用地址
super只能在对象内部使用,而this可以在对象内部使用也可以返回出对象外.
super是死的,编译的时候就定死了super的指向了,而this是活的,在运行时候决定其指向.
再说一下,子类实例化对象,并没有去实例化他的父类对象,也就是说,那个子类对象里面并没有一个父类对象,
那你说没有父类对象,为什么子类构造函数要执行父类的构造函数啦,那是因为需要创建父类的特征赋予子类,但是是由子类所有,而super就是用来区别是是否是父类对象的特征的.
重写父类方法属性,就是再创建了一个子类的特征,当你用this的时候,就覆盖了父类的特征了,但是父类特征还在那儿,用super就能访问道,但是只能在对象的内部使用.对象外面就只能看到覆盖了父类特征的子类特征了.
写完收工,我Cao,写了2个小时.....
其实写了这么一大堆,就是一句:"this是当前对象在堆空间的引用地址,super是当前对象的父类特征的引用"
有什么不同的见解欢迎讨论...共同进步!!!