• 访问者模式


    参考:http://www.cnblogs.com/java-my-life/archive/2012/06/14/2545381.html

    分派的概念

      变量被声明时的类型叫做变量的静态类型(Static Type),有些人又把静态类型叫做明显类型(Apparent Type);而变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type)。比如:

    List list = null;
    list = new ArrayList();

      声明了一个变量list,它的静态类型(也叫明显类型)是List,而它的实际类型是ArrayList。

      根据对象的类型而对方法进行的选择,就是分派(Dispatch),分派(Dispatch)又分为两种,即静态分派动态分派

      静态分派(Static Dispatch)发生在编译时期,分派根据静态类型信息发生。静态分派对于我们来说并不陌生,方法重载就是静态分派。

      动态分派(Dynamic Dispatch)发生在运行时期,动态分派动态地置换掉某个方法。

     静态分派

      Java通过方法重载支持静态分派。用墨子骑马的故事作为例子,墨子可以骑白马或者黑马。墨子与白马、黑马和马的类图如下所示:

    在这个系统中,墨子由Mozi类代表

    public class Mozi {
        
        public void ride(Horse h){
            System.out.println("骑马");
        }
        
        public void ride(WhiteHorse wh){
            System.out.println("骑白马");
        }
        
        public void ride(BlackHorse bh){
            System.out.println("骑黑马");
        }
        
        public static void main(String[] args) {
            Horse wh = new WhiteHorse();
            Horse bh = new BlackHorse();
            Mozi mozi = new Mozi();
            mozi.ride(wh);
            mozi.ride(bh);
        }
    
    }

     显然,Mozi类的ride()方法是由三个方法重载而成的。这三个方法分别接受马(Horse)、白马(WhiteHorse)、黑马(BlackHorse)等类型的参数。

      那么在运行时,程序会打印出什么结果呢?结果是程序会打印出相同的两行“骑马”。换言之,墨子发现他所骑的都是马。

      为什么呢?两次对ride()方法的调用传入的是不同的参数,也就是wh和bh。它们虽然具有不同的真实类型,但是它们的静态类型都是一样的,均是Horse类型。

      重载方法的分派是根据静态类型进行的,这个分派过程在编译时期就完成了

     动态分派

      Java通过方法的重写支持动态分派。用马吃草的故事作为例子,代码如下所示:

    public class Horse {
        
        public void eat(){
            System.out.println("马吃草");
        }
    }
    public class BlackHorse extends Horse {
        
        @Override
        public void eat() {
            System.out.println("黑马吃草");
        }
    }
    public class Client {
    
        public static void main(String[] args) {
            Horse h = new BlackHorse();
            h.eat();
        }
    
    }

     变量h的静态类型是Horse,而真实类型是BlackHorse。如果上面最后一行的eat()方法调用的是BlackHorse类的eat()方法,那么上面打印的就是“黑马吃草”;相反,如果上面的eat()方法调用的是Horse类的eat()方法,那么打印的就是“马吃草”。

      所以,问题的核心就是Java编译器在编译时期并不总是知道哪些代码会被执行,因为编译器仅仅知道对象的静态类型,而不知道对象的真实类型;而方法的调用则是根据对象的真实类型,而不是静态类型。这样一来,上面最后一行的eat()方法调用的是BlackHorse类的eat()方法,打印的是“黑马吃草”

     分派的类型

      一个方法所属的对象叫做方法的接收者,方法的接收者与方法的参数统称做方法的宗量。比如下面例子中的Test类

    public class Test {
    
        public void print(String str){
            System.out.println(str);
        }
    }
  • 相关阅读:
    如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?
    什么是 JavaConfig?
    序列号Sequences
    包Packages
    参数Parameters、变量Variables
    maven配置多个镜像
    各种http报错的报错的状态码的分析
    举例说明同步和异步。
    第二阶段的任务及燃尽图(第二天)
    第二阶段的任务及燃尽图(第一天)
  • 原文地址:https://www.cnblogs.com/Michael2397/p/7806050.html
Copyright © 2020-2023  润新知