java 分派

多态

多态是面向对象的重要特征之一,多态主要体现在重写。

分派涉及到的概念
  • 变量被声明时的类型叫做变量的静态类型(Static Type) 又叫明显类型(Apparent Type)。
  • 变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type)。
  • 根据对象的类型而对方法进行的选择,就是分派(Dispatch)。

根据分派发生的时期,可以将分派分为两种,即分派分静态分派和动态分派。

  • 静态分派(Static Dispatch)发生在编译时期,分派根据静态类型信息发生。方法重载(Overload)就是静态分派。(所谓的:编译时多态)
  • 动态分派(Dynamic Dispatch)发生在运行时期,动态分派动态地置换掉某个方法。面向对象的语言利用动态分派来实现方法置换产生的多态性。(所谓的:运行时多态)
基于静态分配的例子
  public static void main(String[] args) {
      Human h = new Human(); 
      h.sayHello(h);
      Human m = new Man(); 
      h.sayHello(m);
      Human w = new Woman(); 
      h.sayHello(w);

      /*
       * Human称为变量的静态类型,或者叫做外观类型,
       * 后面的Man被称为变量的实际类型。 方法的重载
       * 是通过参数的静态类型作为判断的 ,并且静态类
       * 型是编译器可知的,因此在编译阶段编译器会根
       * 据参数的静态类型决定使用哪个重载版本。
       */

      /*
       * 依赖静态类型来定位方法执行版本的分派动作称为静态
       * 分派。静态分派的典型应用就是方法重载。
       * 
       */

      /*
       * 另一个问题,是编译器虽然能确定出
       * 方法的重载版本,但是在很多情况下
       * 这个重载版本并不是唯一的,只能确
       * 定一个更加合适的版本。例如,重载
       * 的方法中,参数列表除了参数类型不
       * 一样,其他都一样,例接收的参数有ch
       * ar\int\long等,传入参数‘a’,则会调用
       * 需要char类型参数的方法,去掉需要char类型
       * 参数的方法,则会调用需要int类型参数的方
       * 法。这时发生了一次自动类型转换。同样,去掉需要
       * int类型参数的方法,则会调用需要long类
       * 型参数的方法。这里再次发生类型转换,会按照
       * char->int->long->float->double转换类型。
       * 
       */

  }
  public void sayHello(Human h) {
      System.out.println("Human");
  }
  public void sayHello(Man m) {
      System.out.println("man");
  }
  public void sayHello(Woman w) {
         System.out.println("woman");
}
}
 class Man extends Human{
}
 class Woman extends Human{
}
基于动态分派的例子
这里写代码片public class Human1 {
   public static void main(String[] args) {
     Human1 h1 = new Human1();
     h1.say();
     Human1 h2 = new Woman1();
     h2.say();
     Human1 h3 = new Man1();
     h3.say();

     /*
      * 动态分派和重写联系密切
      * Java是通过变量的实际类型在运行期确定执行哪个版本 。
      * 上面3个变量的实际类型不同,会调用各自的方法。
      */
  }

   public void say() {
       System.out.println("human");
   }
}

class Man1 extends Human1{
    @Override
    public void say() {
        // TODO Auto-generated method stub
        System.out.println("man");
    }
}

class Woman1 extends Human1{
    @Override
    public void say() {
        // TODO Auto-generated method stub
        System.out.println("woman");
    }

}

基于动态分配的在接口中也同样适用:

public interface Tech {
    void tech();
}
public class  TechMath implements Tech{
    @Override
    public void tech() {
        // TODO Auto-generated method stub
        System.out.println("我教数学");
    }
}
public class TechChinese implements Tech{
    @Override
    public void tech() {
        // TODO Auto-generated method stub
        System.out.println("我是教语文");
    }
    public static void main(String[] args) {
         Tech t = new TechChinese();
         t.tech();
         Tech t1 = new TechMath();
         t1.tech();
    }
}
面试题

最后看一个例子:

public class Test276 {
  public static void main(String[] args) {
    Collection<?>[] collections = {new HashSet<String>(),new ArrayList<String>(),new HashMap<String,String>().values()};
    Super s = new sub();
    for(Collection<?> c:collections) {
        System.out.println(s.getType(c));
    }
  }

  abstract static class Super{
      public static String getType(Collection<?> c) {
          return "super collection";
      }

      public static String getType(List<?> c) {
          return "super list";
      }

      public static String getType(ArrayList<?> c) {
          return "super arraylist";
      }

      public static String getType(Set<?> c) {
          return "super set";
      }
      public static String getType(HashSet<?> c) {
          return "super hashset";
      }

  }
  static class sub extends Super{
      public static String getType(Collection<?> collection) {
          return "Sub"; }
   }
}

执行结果:super collection 打印3次

本例中,如果去掉static,那么本例就是打印子类的方法。如果子类参数类型不符合,就往父类找,就近找,父类找不到,就报错。

参考学习
参考学习

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值