静态分配与静态分配目标的过程

1. 静态分派

public class StaticDispatch {

    static abstract class Human {
    }

    static class Man extends Human {
    }

    static 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 static void main(String[] args) {
        Human man = new Man();
        Human woman = new Woman();
        StaticDispatch sr = new StaticDispatch();
        sr.sayHello(man);
        sr.sayHello(woman);
    }
}

运行结果为:

hello,guy!
hello,guy!

分析:

Human 称为变量的 静态类型/外观类型

Man 称为变量的 实际类型/运行时类型

两种类型都可能发生变化,区别是:

静态类型的变化仅仅在使用时发生,变量本身的静态类型不会发生改变,并且最终的静态类型是在编译期可知的;

实际类型变化的结果在运行期才可确定,编译器在编译程序的时候并不知道一个对象的实际类型是什么;

// 实际类型变化
Human human = (new Random()).nextBoolean() ? new Man() : new Woman();

// 静态类型变化
sr.sayHello((Man) human);
sr.sayHello((Woman) human);

对象human的实际类型是可变的,编译期间它完全是个”薛定谔的人“,到底是Man还是Woman,必读等到程序运行到这行的时候才能确定。

虚拟机(准确地说是编译器)在重载时是通过参数的静态类型而不是实际类型作为判定的依据的。

所有依赖静态类型来决定方法执行版本的分派动作,都称为静态分派。

静态分派的典型代表就是方法重载。

静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的(编译器来执行)。

 

2. 静态分配目标的过程

Javac编译器虽然能确定出方法的重载版本,但在很多情况下这个重载版本并不是”唯一的“,往往只能确定一个”相对更合适的“版本。

重载方法匹配优先级:

public class Overload {

    public static void sayHello(Object arg) {
        System.out.println("hello Object");
    }

    public static void sayHello(int arg) {
        System.out.println("hello int");
    }

    public static void sayHello(long arg) {
        System.out.println("hello long");
    }

    public static void sayHello(Character arg) {
        System.out.println("hello Character");
    }

    public static void sayHello(char arg) {
        System.out.println("hello char");
    }

    public static void sayHello(char... arg) {
        System.out.println("hello char ...");
    }

    public static void sayHello(Serializable arg) {
        System.out.println("hello Serializable");
    }

    public static void main(String[] args) {
        sayHello('a');
    }
}

char -> int -> long -> Character -> Serializable -> 父类(若有多个父类,继承关系中从下往上开始搜索)-> 可边长参数。

此代码演示了编译期间选择静态分派目标的过程,这个过程也是Java语言实现方法重载的本质

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值