学了还蛮久的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高级特性与最佳实践》