Java_分派_静态分派

来源:互联网 发布:mysql update性能优化 编辑:程序博客网 时间:2024/05/22 11:42

例:

package jvm;class StaticDispatch {    static abstract class Human {    }    static class Man extends Human {    }    static class Women 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(Women guy) {        System.out.println("Hello,lady!");    }    public static void main(String[] args) {        Human man = new Man();        Human women = new Women();        StaticDispatch dispatch = new StaticDispatch();        dispatch.sayHello(man);        dispatch.sayHello(women);    }}

运行结果:
Hello,guy!
Hello,guy!

为什么会执行参数类型为Human的重载呢?在解决这个问题之前,我们先按如下代码定义两个重要的概念:
Human man = new Man();
我们把上面代码中的“Human”称为变量的静态类型(Static Type)或者外观类型(Apparent Type),后面的“Man”则称为变量的实际类型(Actual Type),静态类型和实际类型在程序中都可以发生一些变化,区别是静态类型的变化仅仅在使用时发生,变量本身的静态类型不会被改变,并且最终的静态类型实在编译器可知的;而实际类型变化的结果在运行期才可确定,编译器在编译程序的时候并不知道一个对象的实际类型是什么。虚拟机(准确地说是编译器)在重载时时通过参数的静态类型而不是实际类型作为判断依据的,并且静态类型是编译器可知的,所以在编译阶段,Javac编译器就根据参数的静态类型决定使用哪个重载版本,所以选择了sayHello(Human)作为调用目标。
所有依赖静态类型来定位方法执行版本的分派动作,都称为静态分派。静态分派的最典型应用就是方法重载。静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的。

0 0
原创粉丝点击