在《深入理解Java虚拟机》第2版(周志明著)一书中,作者总结到:
今天(直至还未发布的Java1.8)的Java语言是一门静态多分派、动态单分派的语言。
这里主要有4个概念:
Java语言层面:重载、重写;
虚拟机层面:静态分派、动态分派
预先说说前置概念:
Human man = new Man();
语句中,“Human”是变量man的静态类型(Static Type),或者叫做外观类型(Apparent Type)。后面的“Man”则称为变量的实际类型(Actual Type)。
方法的接收者(Receiver):看语句:
man.sayHello();
woman.sayHello();
这里,对象man和对象woman都是将要执行的成员方法“sayHello()”的所有者,称为接收者(Receiver)。
接下来说说分派的定义:
宗量:方法的接收者与方法的参数统称为方法的宗量。
单分派:根据一个宗量对目标方法进行选择;
多分派:根据多于一个宗量对目标方法进行选择。
静态分派:所有依赖静态类型来定位方法执行版本的分派称为静态分派。静态分派的典型应用是方法重载。虚拟机(准确地说是编译器)在重载时是通过参数的静态类型而不是实际类型作为判定依据的。
动态分派:在运行期根据实际类型确定方法执行版本的分派过程称为动态分派。Java语言中方法重写的本质就是:虚拟机是根据方法接收者的实际类型来确定方法执行版本的。
这篇文章里要记住的就两句话:
**方法重载的本质是虚拟机是根据参数的静态类型来确定方法版本的;
方法重写的本质是虚拟机是根据方法接收者的实际类型来确定方法版本的。**
下面是书中给出的静态分派和动态分派的例子:
方法重载:
package chwn.wuba.com.activitymode;
/**
* Created by changwenna on 2017/3/17.
*/
public class StaticDispatch {
abstract class Human {
}
class Man extends Human {
}
class Woman extends Human {
}
public void sayHello(Human guy) {
System.out.println("hello,guy!");
}
public void sayHello(Man guy) {
System.out.println("hello,gentleman!");
}
public void sayHello(Woman guy) {
System.out.println("hello,lady!");
}
public void test() {
Human man = new Man();
Human woman = new Woman();
this.sayHello(man);
this.sayHello(woman);
this.sayHello((Man) man);
this.sayHello((Woman) woman);
}
}
然后调用:
StaticDispatch sr = new StaticDispatch();
sr.test();
请问打印结果是啥?
参考答案:
I/System.out: hello,guy!
I/System.out: hello,guy!
I/System.out: hello,gentleman!
I/System.out: hello,lady!
方法重写:
package chwn.wuba.com.activitymode;
/**
* Created by changwenna on 2017/3/17.
*/
public class DynamicDispatch {
class Human {
protected void sayHello() {
System.out.println("human say hello");
}
}
class Man extends Human {
@Override
protected void sayHello() {
System.out.println("man say hello");
}
}
class Woman extends Human {
@Override
protected void sayHello() {
System.out.println("woman say hello");
}
}
public void test() {
Human human = new Human();
Human man = new Man();
Human woman = new Woman();
human.sayHello();
man.sayHello();
woman.sayHello();
}
}
然后调用:
DynamicDispatch sr = new DynamicDispatch();
sr.test();
请问打印结果是啥?
参考答案:
I/System.out: human say hello
I/System.out: man say hello
I/System.out: woman say hello