咱们先来看stackoverflow上的一个问题,先上代码ide
1 public class Piece{ 2 public static void main (String [] args){ 3 Piece p2 = new Knight(); 4 Knight p1 = new Knight(); 5 p1.capture(p2); 6 p2.capture(p1); 7 } 8 public void capture(){ 9 System.out.println("Capture"); 10 } 11 public void capture(Piece p){ 12 System.out.println("I'm bored"); 13 } 14 } 15 class Knight extends Piece{ 16 public void capture(Piece p){ 17 System.out.println("Knight is bored"); 18 } 19 public void capture(Knight k){ 20 System.out.println("Too slow buddy"); 21 } 22 }
问的是这段代码输出是什么?答案是学习
Knight is bored
Knight is bored
由于刚刚开始学习Java,在跟CS61B的课,而后老师讲到dynamic type和static type的时候,本身有点模糊,因而在stackoverflow上搜索相关的问题,果真发现一个典型的动态绑定的问题,仔细分析以后感受收获挺大的,对继承的理解更加深刻了。spa
分析:这个是怎么回事呢?首先看第三第四行,p1确定是一个Knight类型,而对于p2, 它是一个Piece类型的引用,指向了一个Knight类的对象,此时咱们称Piece为static type,而Knight为dynamic类型。code
p1.capture(p2),也就是Knight.capture(Piece),Knight类里恰好定义了这个方法,即输出"Knight is bored"。对象
p2.capture(p1),也就是Piece.capture(Knight),乍一看Piece里面没有这个方法啊。这里应该是有一个赋值,即Piece p = p1,把子类的引用赋给父类,这是容许的。因此实际上调用的Piece.capture(Piece),那么结果应该输出"I'm bored"啊,怎么会是"Knight is bored"呢?前面已经说了,p2实际上指向了一个Knight类的对象,而在Knight类中恰好Ovriride了这个Piece.capture(Piece)方法,也就是Knight.capture(Piece),因此应该调用这个方法,即输出"Knight is bored"。blog
好如今咱们把这个Override的方法注释掉,看看结果如何?继承
1 public class Piece{ 2 public static void main (String [] args){ 3 Piece p2 = new Knight(); //static Piece, dynamic Knight 4 Knight p1 = new Knight(); 5 p1.capture(p2); 6 p2.capture(p1); 7 } 8 public void capture(){ 9 System.out.println("Capture"); 10 } 11 public void capture(Piece p){ 12 System.out.println("I'm bored"); 13 } 14 } 15 class Knight extends Piece{ 16 // public void capture(Piece p){ //这里override了Piece中的方法 17 // System.out.println("Knight is bored"); 18 // } 19 public void capture(Knight k){ 20 System.out.println("Too slow buddy"); 21 } 22 }
输出结果是:class
I'm bored I'm bored
分析:第二个输出刚刚已经解释了,由于如今没有override的方法了,因此就直接调用Piece类中的Piece.capture(Piece p)方法。那么第一个输出又是怎么回事呢?p1.capture(p2),也就是Knight.capture(Piece),这里不能调用Knight.capture(Knight k)这个方法,由于Knight k = p2,这是不合法的,Java中不容许把父类的引用赋给子类的引用变量。那么既然如此,Knight类中岂不是没有这个方法了吗?不要忘记,Knight类是继承在Piece类上的,也就是Knight类型也能调用Piece类中的方法,也就是Piece.capture(Piece)方法,因此输出是"I'm bored"。变量
如今咱们知道,Piece p2 = new Knight()这句特殊之处就在于,有一个查找在子类中是否存在override的方法,若是存在就调用子类中这个override的方法,若是没有就使用父类中的方法。若是是这样定义的:Piece p2 = new Piece(),那么不管在子类中有没有override方法,都不会去调用子类的方法,而是直接调用父类的方法。以下:搜索
1 public class Piece{ 2 public static void main (String [] args){ 3 // Piece p2 = new Knight(); //static Piece, dynamic Knight 4 Piece p2 = new Piece(); 5 Knight p1 = new Knight(); 6 p1.capture(p2); 7 p2.capture(p1); 8 } 9 public void capture(){ 10 System.out.println("Capture"); 11 } 12 public void capture(Piece p){ 13 System.out.println("I'm bored"); 14 } 15 public void capture(Knight p){ 16 System.out.println("Hello"); 17 } 18 } 19 class Knight extends Piece{ 20 public void capture(Piece p){ //这里override了Piece中的方法 21 System.out.println("Knight is bored"); 22 } 23 public void capture(Knight k){ //这里override了Piece中的方法 24 System.out.println("Too slow buddy"); 25 } 26 }
输出结果是:
Knight is bored
Hello
咱们能够看到,即便在Knight类中override了.capture(Knight)方法,因为p2一直就是一个Piece类,根本不会调用Knight类中的方法,因此p2.capture(p1),也就是Piece.capture(Knight),输出"Hello"。第四行改为Piece p2 = new Knight(),则输出就是:
Knight is bored
Too slow buddy
第二个输出调用的就是Knight类中override的方法。