java的多态性

来源:互联网 发布:姚明05-06赛季数据 编辑:程序博客网 时间:2024/06/05 16:27

学了还蛮久的java,一直知道其具备面向对象的三个基本特征:继承、封装和多态。但是一直没怎么明白多态性。今天看了书,大概总结一下(感觉不是很全面)。

java中多态性分为动态多态性和静态多态性。静态多态性就是指方法的重载,是一个类的行为。动态多态性是指方法的重写,即多态是指在有继承关系的两个或两个以上的类的行为。

下面是一个重写的小Demo
public class DynamicTest {    static abstract class Human{        protected abstract void sayHello();    }    static class Man extends Human{        @Override        protected void sayHello() {            System.out.println("man say hello");        }    }    static class Woman extends Human{        @Override        protected void sayHello() {            System.out.println("woman say hello");        }    }    public static void main(String[] args) {        Human man=new Man();        Human woman=new Woman();        man.sayHello();        woman.sayHello();        man=new Woman();        man.sayHello();    }}

结果:
man say hello
woman say hello
woman say hello

以上Man类和Woman类重写了sayHello方法,属于重写。

下面来看下重载的匹配优先级

import java.io.Serializable;public class Overload {    public static void sayHello(Object arg){        System.out.println("Object sayHello");    }    public static void sayHello(int arg){        System.out.println("int sayHello");    }    public static void sayHello(char arg){        System.out.println("char sayHello");    }    public static void sayHello(long arg){        System.out.println("long sayHello");    }    public static void sayHello(Character arg){        System.out.println("Character sayHello");    }    public static void sayHello(char...arg){        System.out.println("char... sayHello");    }    public static void sayHello(Serializable arg){        System.out.println("Serializable sayHello");    }    public static void main(String[] args) {        sayHello('a');    }}

我们知道‘a’是一个char类型的数据,自然会寻找参数类型为char的重载方法
当把sayHello(char arg)注释掉时,会执行sayHello(int arg)重载方法,发生类型转换
当把sayHello(int arg)注释掉时,会执行sayHello(int arg)重载方法,发生类型转换
这时发生了两次自动类型转换,’a’转型成整数97,再转化为长整形97L,匹配了参数类型为long的重载。要是有float、double类型的重载,则按照char->int->long->float->double的顺序进行匹配。

当我们继续注释掉sayHello(long arg)时,那么会执行sayHello(Character arg)重载方法,这时发生一次自动装箱,’a’被包装为它的封装类型java.lang.Character,所以匹配到参数类型为Character的重载。
继续注释掉sayHello(Character arg),那么会执行sayHello(Serializable arg)重载方法。这时因为java.lang.Serializable是java.lang.Character类实现的一个接口,当自动装箱以后还是找不到箱类,但是找到箱类实现了的接口类型,所以紧接着又发生了一次自动转型。char可以转型成int,但是Character是绝不会转型成Integer的,它只能安全地转型为它实现的接口或父类。
继续注释掉sayHello(Serializable arg),那么会执行sayHello(char…arg)重载方法,可见变长参数的重载优先级是最低的,这时候字符’a’被当成一个数组元素。

本文参考《深入理解java虚拟机–JVM高级特性与最佳实践》

0 0
原创粉丝点击