• 静态分配


    静态方法会在类加载期就进行解析,而静态方法显然也是可以拥有重载版本的,选择重载版本的过程也是通过静态分派完成的。

    public class StaticDispatch{
    
        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((Man)man);
            sr.sayHello((Woman) woman);
    }
    }

    //结果

    hello,guy!
    hello,guy!
    hello,gentleman!
    hello,lady!

    我们把上面代码中的“Human”称为变量的静态类型(Static Type),或者叫做的外观类型(Apparent Type),后面的“Man”则称为变量的实际类型(Actual Type),静态类型和实际类型在程序中都可以发生一些变化,区别是静态类型的变化仅仅在使用时发生,变量本身的静态类型不会被改变,并且最终的静态类型是在编译期可知的;而实际类型变化的结果在运行期才可确定,编译器在编译程序的时候并不知道一个对象的实际类型是什么。

    所有依赖静态类型来定位方法执行版本的分派动作称为静态分派。静态分派的典型应用是方法重载静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的。 

    下面的代码更适合演示在编译期间确实调用方法的版本

    public class maintest {
        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 main(String[] args) {
            sayHello('a');
        }
    }

    执行结果: 

    //执行结果
    hello char
    
    对应字节码
             0: bipush        97
             2: invokestatic  #10                 // Method sayHello:(C)V
             5: return

    这很好理解,'a'是一个char类型的数据,自然会寻找参数类型为char的重载方法,如果注释掉sayHello(char arg)方法,那输出会变为:

    //hello int
    //对应字节码
    
             0: bipush        97
             2: invokestatic  #9                  // Method sayHello:(I)V
             5: return

    这时发生了一次自动类型转换,'a'除了可以代表一个字符串,还可以代表数字97(字符'a'的Unicode数值为十进制数字97),因此参数类型为int的重载也是合适的。

    我们继续注释掉sayHello(int arg)方法,那输出会变为:

    hello long
    
    //对应字节码
             0: ldc2_w        #8                  // long 97l
             3: invokestatic  #10                 // Method sayHello:(J)V
             6: return

    实际上自动转型还能继续发生多次,按照char->int->long->float->double的顺序转型进行匹配.

  • 相关阅读:
    USB设备的一些概念
    DDK 的一些笔记
    Android cannot access localhost?
    Run or Debug Android application 弹出了SDL_app:emulator.exe 的错误 说我指令引用的内存不能为可写的
    Cannot refer to a nonfinal variable music inside an inner class defined in a different method
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.clm.activity/com.clm.activity
    Failed to install helloworld.apk on device 'emulator5554': timeout
    SortedMap接口
    Automatic Target Mode: Preferred AVD '2.3.3' is not available. Launching new emulator.
    Only one expression can be specified in the select list when the subquery is not introduced with EXI
  • 原文地址:https://www.cnblogs.com/snow-man/p/10609317.html
Copyright © 2020-2023  润新知