zoukankan      html  css  js  c++  java
  • java中的多态

      多态是面向对象三大特性之一(另外两个叫封装和继承),也是三兄弟中最不好理解的一个。网上流行的说法是分两类多态:编译时和运行时。有的人把重载、泛型算到编译时多态头上,有的人不同意,我站在后面这一队。为啥?因为java语言的经典著作《Thinking in JAVA》里说:多态通过分离做什么和怎么做,从另一个角度将接口和实现分离开来。这里的接口泛指基类、接口类,因此多态应该基于类的继承或者接口的实现而言,而重载、泛型并未涉及。

      先说继承,看例子:

      父类:

    abstract class Death
    {
        abstract void printDeathWay();
    }

      子类:

    public class AccidentDeath extends Death
    {
        
        @Override
        public void printDeathWay()
        {
            System.out.println("I'm killed in an accident.");
            
        }
        
    }
    public class DisasterDeath extends Death
    {
        
        @Override
        public void printDeathWay()
        {
           System.out.println("I'm killed by a disaster.");
            
        }
        
        public static void main(String[] args)
        {
            Death death = new AccidentDeath();
            death.printDeathWay(); // 多态:Death -> AccidentDeath
            death = new DisasterDeath(); // 多态:Death -> DisasterDeath
            death.printDeathWay();
        }
    }

      执行结果:

    I'm killed in an accident.
    I'm killed by a disaster.

      我们看到父类Death执行了printDeathWay方法有两个不同的子类结果,因为子类分别重写了该方法,这就是多态。同样的,如果把Death的abstract class改为interface,子类extands改为implememts,执行结果仍然不变。接口的行为由实现类分别去处理。这里抽象方法printDeathWay调用的时候用到了动态绑定。

      啥是动态绑定?将一个方法调用同一个方法主体关联起来被称为绑定。如果在程序执行之前就绑定了,就叫前期绑定或静态绑定,比如static方法、私有方法或者构造器,编译器很明确该调用哪个方法。比如上面的main方法就是一个static方法,编译器在执行main方法前就知道去调用该main方法。但如果是在运行时根据对象的类型进行绑定,那么就叫后期绑定,也叫做动态绑定或运行时绑定。动态绑定是java的默认方式(除了上面静态绑定之外的方法调用),正式因为天赋此种异凛,才导致了多态特性的诞生。那么动态绑定怎么做到的呢?JVM为每个方法签名和实际调用方法建立映射关系,每次调用方法时JVM都去映射关系表里查找。比如上面调用death.printDeathWay()时,JVM先找到death的具体类型(比如是AccidentDeath),然后查找该类的方法映射表(printDeathWay() -> AccidentDeath.printDeathWay()),最后调用AccidentDeath.printDeathWay()。

      最后再说下重载的情况:

        public void printSomething(String msg)
        {
            System.out.println(msg);
        }
        
        public void printSomething(int count)
        {
            System.out.println(count);
        }

      上面的两个方法名称相同,但参数类型不同,乍一看也有点多态的意思,同一个方法调用支持不同的类型,但我们要明白,重载是横向的,而多态是纵向的。泛型也是同样的道理,它们都是编译器能识别的(重载如果方法签名一样则编译报错,泛型传入类型不一致也编译报错)。只有纵向的继承(包括接口的实现)才是多态的特征,这就是为什么我认为没有编译时多态这一说法的根源。

  • 相关阅读:
    paramiko模块
    linux 文件权限管理
    itext 生成pdf文件添加页眉页脚
    Python3 断言
    net core WebApi——文件分片上传与跨域请求处理
    Linux配置部署_新手向(二)——Nginx安装与配置
    Linux配置部署_新手向(一)——CentOS系统安装
    net core Webapi基础工程搭建(七)——小试AOP及常规测试_Part 2
    net core Webapi基础工程搭建(六)——数据库操作_Part 2
    net core Webapi基础工程搭建(七)——小试AOP及常规测试_Part 1
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/9494718.html
Copyright © 2011-2022 走看看