先来看两段代码。
public class Parent { public void init(){ System.out.println("init parent"); } public void demo(){ System.out.println("demo parent"); } }
public class Son extends Parent{ public void init(){ super.init(); System.out.println("init son"); } public void demo(){ System.out.println("demo son"); } public static void main(String[] args) { Parent son=new Son(); son.init(); } }
这个的输出相信大家很好猜到:
init parent init son
因为super.init()的含义就是调用父类方法。这里就是先调用了父类的init(),再调用了子类的init()。
接下来我们在父类中增加一行代码
public class Parent { public void init(){ System.out.println("init parent"); this.demo(); } public void demo(){ System.out.println("demo parent"); } }
子类不变,这时的this代表什么呢?我们知道,子类继承父类,子类中含有一个指向父类对象的引用。而这里的this在Parent父类中,是否指的是父类对象调用的父类的demo()方法呢???我们看一下输出
init parent demo son init son
纳尼???我们认为输出的父类的demo方法,结果实际上输出的却是子类的demo方法。 这个就是我们所说的多态了,方法是保存在栈中,只有在运行时才会动态绑定,所以我们在父类中调用this.demo()方法时,它会在运行时动态绑定寻找到子类的demo()方法。
还可以理解为非静态的方法在调用时默认在方法第一个参数中传入了个this对象,则init()方法实际调用的是init(this),在调用super.init()时把this传入super(),则parent中init()方法调用this实际上是son。
好了,你是不是觉得已经掌握了this的含义了,我们再来看下面一段代码
public class Parent { public String name="tom"; public void say(){ System.out.println(this.name); } public void init(){ System.out.println("init parent"); this.demo(); } public void demo(){ System.out.println("demo parent"); } } public class Son extends Parent{ public String name="jack"; public void say(){ super.say(); System.out.println(this.name); } public void init(){ super.init(); System.out.println("init son"); } public void demo(){ System.out.println("demo son"); } public static void main(String[] args) { //当前运行类son Parent son=new Son(); son.say(); } }
这段代码中我们新增了一个字段name,父类和子类中都有这个字段。
我们执行上面的代码,两个say()方法中,分别调用this.name,这是访问name字段,那么根据刚才的经验,是不是应该输出两个jack呢?我们看看结果。
tom jack
又与想象的不一样!这次是为什么呢?因为字段是在new出来之后保存在堆中的,谁调用就是谁的。这时就要看它声明的是什么。
public class Son extends Parent{ public String name="jack"; public void say(){ super.say(); System.out.println(this.name); } public void init(){ super.init(); System.out.println("init son"); } public void demo(){ System.out.println("demo son"); } public static void main(String[] args) { //当前运行类son Son son=new Son(); System.out.println(son.name); } }
再来看一个问题,这里我们输出的是什么呢?
jack
这个没问题,是子类的变量jack
public class Son extends Parent{ public String name="jack"; public void say(){ super.say(); System.out.println(this.name); } public void init(){ super.init(); System.out.println("init son"); } public void demo(){ System.out.println("demo son"); } public static void main(String[] args) { Parent son=new Son(); System.out.println(son.name); } }
再来看看这里输出的是什么?
tom
好吧,为什么不是子类的字段呢?我们来总结一下多态
多态的执行特点:
成员变量编译运行看左边
成员方法编译看左边,运行看右边
画出内存图就是,成员变量两个,成员方法一个。
