码迷,mamicode.com
首页 > 编程语言 > 详细

从stackoverflow上的一个问题看Java动态绑定

时间:2016-05-09 23:29:06      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:

我们先来看stackoverflow上的一个问题,先上代码

 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上搜索相关的问题,果然发现一个典型的动态绑定的问题,仔细分析之后感觉收获挺大的,对继承的理解更加深入了。

分析:这个是怎么回事呢?首先看第三第四行,p1肯定是一个Knight类型,而对于p2, 它是一个Piece类型的引用,指向了一个Knight类的对象,此时我们称Piece为static type,而Knight为dynamic类型。

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"。

 

好现在我们把这个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 }

输出结果是:

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的方法。

 

从stackoverflow上的一个问题看Java动态绑定

标签:

原文地址:http://www.cnblogs.com/ttylcc/p/5475822.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!