一,介绍
先看源代码:
上图代码有父类A,子类B,还有一个main方法,初看很简单,考察的就是一个向上转型的基本知识,先确定编译类型和运行类型,由A a= new B();可以看出,运行类型是B,编译类型是A,再看调用的是方法还是属性,看代码得第一个输出语句调用的是方法,所以要先到运行类型B类中去查找sum方法,i就是B类的属性i值,所以返回20+20=40,第一个输出40,第二个调用的是方法,所以还是到B类中去找sum1方法,故返回20+10=30.
以上是考察向上转型的代码运行方法,引出下面的动态绑定机制。
将源代码稍作修改,如下:
package com.whpu.DynamicBinding.java; public class Dynamic { public static void main(String[] args) { A a=new B(); System.out.println(a.sum()); System.out.println(a.sum1()); } } class A{ public int i=10; public int sum(){ return getl()+10; } public int sum1(){ return i+10; } public int getl(){ return i; } } class B extends A{ public int i=20; // public int sum(){ // return i+20; // } public int getl(){ return i; } public int sum1(){ return i+10; } }
将B类中的sum方法注释掉,所以不起作用了,当执行第一个输出语句时,还是先到运行类型B中找sum方法,发现找不到,故向上找父类A,在父类A中找到了sum方法,但是返回的内容中由getl方法,而getl方法在A,B中都有,到底该调用哪一个呢?这个时候就要用到动态绑定机制了。
按照动态绑定机制的规定。
①,当调用对象方法的时候,该方法会和该对象的内存地址/动态对象绑定。
②,当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用。
按照方法一,getl方法是对象方法,这个方法会和这个对象,即a对象的动态类型(即B类)绑定,所以getl方法会调用B类的getl方法而不会调用A类的getl方法,所以最后第一个输出语句输出的结果就是20+10=30.第二个还是30.
验证方法二:如下源代码
package com.whpu.DynamicBinding.java; public class Dynamic { public static void main(String[] args) { A a=new B(); System.out.println(a.sum()); System.out.println(a.sum1()); } } class A{ public int i=10; public int sum(){ return getl()+10; } public int sum1(){ return i+10; } public int getl(){ return i; } } class B extends A{ public int i=20; // public int sum(){ // return i+20; // } public int getl(){ return i; } // public int sum1(){ // return i+10; // } }
再将B类的sum1方法注释掉,不起作用,所以当调用main方法中的第二个输出语句时,其执行运行类型B时找不到sum1方法,就会找到父类A的sum1方法,这是出现了i,问题来了,这个i是用A类的i值呢还是用B类的i值呢?这就要看方法二的说明了,当调用对象方法属性时,没有动态绑定机制,哪里声明,哪里调用,所以这个i值就是调用的A类的i值10,输出结果就是10+10=20.