Java中的分派
首先需要理解一下静态类型和动态类型。找了很多资料,没有在java的书中找到关于这两种类型的具体定义,但是在C++的书中找到了下面的定义,这可能就是java被称为是 C++- 的原因之一吧。:)
静态类型与动态类型
- 静态类型:不需要考虑表达式执行期的语义,仅从表达式的字面的形式就能够决定的类型,在编译期确定的变量类型,并且在运行期不会改变。
- 动态类型:由一个左值表达式指出的左值的动态类型,是其所引用的对象的最狭义类型,在运行期决定具体的变量类型,可以在运行期改变。即:基类引用所引用的对象的实际类型。
左值和右值
按字面意思,通俗地说。以赋值符号 = 为界,= 左边的就是左值,= 右边就是右值。
比如:(1) int b = 3;(2) int a =b;第(2)行代码,a为左值,b为右值。
-
更深一层,可以将 L-value 的 L, 理解成 Location,表示定位,地址。将R-value 的 R 理解成Read,表示读取数据。现在的计算机数据放在内存。内存有两个很基本的属性:内存地址和内存里面放的数据。想象完全一样的箱子。每个箱子有个编号,用来区分到底是哪个箱子,箱子里面可以放东西。内存地址相当于箱子的编号,内存的数据,相当于箱子里面放的东西。
-
变量名编译之后,会映射成内存地址。看看a = b的含义。其实就是 将 “b地址内存里面的数据”,放到”a地址内存”中。
——百度百科
静态分派和动态分派
静态分派:
- 依赖静态类型 确定方法执行版本的分派。[ 判断参数是什么类型]
- 编译期发生。
动态分派:
- 依赖实际类型 确定方法执行版本的分派。[ 判断实际对象是什么类型]
- 向上转型后调用子类重写的方法。
- 运行期(根据实际类型)决定。
静态分派示例:
/**
* Create by zhaihongwei on 2018/4/8
*/
public class StaticDispatch {
public void sayHello(People people) {
System.out.println("你好,我是人!");
}
public void sayHello(China china) {
System.out.println("你好,我是中国人!");
}
public void sayHello(American american) {
System.out.println("你好,我是美国人!");
}
}
/**
* Create by zhaihongwei on 2018/4/8
*/
public class People {
}
/**
* Create by zhaihongwei on 2018/4/8
*/
public class China extends People {
}
/**
* Create by zhaihongwei on 2018/4/8
*/
public class American extends People{
}
测试类:
/**
* Create by zhaihongwei on 2018/4/8
*/
public class Test {
public static void main(String[] args) {
StaticDispatch dispatch = new StaticDispatch();
People people = new People();
People china = new China();
People american = new American();
dispatch.sayHello(people);
dispatch.sayHello(china);
dispatch.sayHello(american);
}
}
测试结果:
你好,我是人!
你好,我是人!
你好,我是人!
动态分派示例:
/**
* Create by zhaihongwei on 2018/4/8
*/
public class People {
public void sayHello() {
System.out.println("你好,我是人!");
}
}
/**
* Create by zhaihongwei on 2018/4/8
*/
public class China extends People {
@Override
public void sayHello() {
System.out.println("你好,我是中国人!");
}
}
/**
* Create by zhaihongwei on 2018/4/8
*/
public class American extends People{
@Override
public void sayHello() {
System.out.println("你好,我是美国人!");
}
}
测试类:
/**
* Create by zhaihongwei on 2018/4/8
*/
public class Test {
public static void main(String[] args) {
People people = new People();
People china = new China();
People american = new American();
people.sayHello();
china.sayHello();
american.sayHello();
}
}
测试结果:
你好,我是人!
你好,我是中国人!
你好,我是美国人!
结论:
从上面的例子看出,变量的动态类型(实际类型)是在运行期确定的,重载方法是根据参数静态类型选择对应方法,重写方法的调用是根据动态类型来调用的。即:JAVA中重载为静态风派,重写为动态分派。