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);
    }

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

posted on 2018-08-17 18:01  不想下火车的人  阅读(200)  评论(0编辑  收藏  举报

导航