提示:以下是本篇文章正文内容
一、Java动态机制
规则:
(1)当调用对象方法时,该方法会和该对象的内存地址(也就是运行类型)绑定。
(2)当调用属性时,没有动态绑定机制,属性在当前类声明,就在当前类使用。
二、详细案例
1. 结合多态的向上转型,分析下面代码输出结果
代码如下:
class AAA{
public int i = 10;
public int sum_1(){return get() + 10;}
public int sum_2(){return i + 10;}
public int get(){return i;}
}
class BBB extends AAA{
public int i = 20;
public int sum_1(){return i + 20;}
public int sum_2(){return i + 10;}
public int get(){return i;}
}
// main方法中
AAA a = new BBB(); // 向上转型,看运行类型,BBB()是运行类型
System.out.println(a.sum_1()); // 看子类BBB中的sum_1,返回40
System.out.println(a.sum_2()); // 同理,返回30
2.再看下面代码,分析输出结果
代码如下:
class AAA{
public int i = 10;
public int sum_1(){return get() + 10;}
public int sum_2(){return i + 10;}
public int get(){return i;}
}
class BBB extends AAA{
public int i = 20;
// public int sum_1(){return i + 20;}
public int sum_2(){return i + 10;}
public int get(){return i;}
}
// main方法中
AAA a = new BBB(); // 向上转型,BBB()是运行类型
System.out.println(a.sum_1()); // 返回多少??
分析:由多态的向上转型可知,首先先去子类BBB中查找sum_1方法,由于没有找到,继承机制发挥作用再去父类AAA中查找,在父类中找到sum_1方法,该方法中返回 get() + 10; 此时关键就看这里的get() 是如何调用?
此时产生动态绑定机制,先看运行类型,运行类型是BBB,所以get()方法先去运行类型BBB中查找,BBB中get()方法return i,此时的 i 就是子类中的 i = 20,返回给父类sum_1中,所以最后结果输出为 20 + 10 = 30,输出30.
3.再看下面代码,分析输出结果
代码如下:
class AAA{
public int i = 10;
public int sum_1(){return get() + 10;}
public int sum_2(){return i + 10;}
public int get(){return i;}
}
class BBB extends AAA{
public int i = 20;
public int sum_1(){return i + 20;}
// public int sum_2(){return i + 10;}
public int get(){return i;}
}
// main方法中
AAA a = new BBB(); // 向上转型,BBB()是运行类型
System.out.println(a.sum_2()); // 返回多少?
分析:首先还是先去子类BBB中查找sum_2方法,由于没有找到,继承机制发挥作用再去父类AAA中查找,在父类中找到sum_2方法,该方法中返回 i + 10; 此时结果输出什么呢?
由于属性不存在动态绑定机制,属性在哪里声明就在哪里调用。所以此时的 i 就是当前类AAA中的 i = 10,最后结果输出为 10 + 10 = 20,输出20.
总结
在看JDK源码时,一定要注意动态绑定机制,只有方法存在动态绑定机制,看到代码就想到编译类型和运行类型,方法和运行类型动态绑定。