Java面向对象3个基本特征:继承、封装和多态;多态主要体现在重载和重写;
1、静态分派
静态分派与重载有关,虚拟机在重载时是通过参数的静态类型,而不是运行时的实际类型作为判定依据的;静态类型在编译期是可知的;
1)基本类型
以char为例,按照char>int>long>double>float>double>Character>Serializable>Object>...(变长参数,将其视为一个数组元素)
变长参数的重载优先级最低
(注意char到byte或short之间的转换时不安全的)
2)引用类型:则需要根据继承关系进行匹配,注意只跟其编译时类型即静态类型相关
2、动态分派
动态分派与重写(Override)相关
3、示例
1)静态分派
class A
{
}
class B extends A
{
}
class C extends A
{
}
class D extends B implements E,
F {
}
interface E
{
}
interface F
{
}
public class Main1 extends A
{
public void test(A a)
{
System.out.println("A");
}
public void test(B b)
{
System.out.println("B");
}
public void test(C c)
{
System.out.println("C");
}
// 填上下面的方法,D转化为父类进行匹配,转化为B,E,F等效,无法找到最优匹配,故会编译报错
//
public void test(E e)
//
{
//
System.out.println("E");
//
}
public static void main(String[] args)
{
A aa = new A();
A ab = new B();
A ac = new C();
B b = new B();
B bd = new D();
D d = new D();
//
C ca = (C) new A();//此编译时会发生错误
C ca = new C();
/* 根据静态分配,重载只与其静态类型相关,若无对应类型,则执行隐式转换进行匹配 */
Main1 main1 = new Main1();
main1.test(aa);// 输出A
main1.test(ab);// 输出A
main1.test(ac);// 输出A
main1.test(b); // 输出B
main1.test(bd);// 输出B
main1.test(ca);// 输出C
main1.test(d); // 输出B
}
}
javap解析结果:
2)动态分派:与动态类型相关
class A
{
public void test()
{
System.out.println("A");
}
}
class B extends A
{
public void test()
{
System.out.println("B");
}
}
class C extends A
{
public void test()
{
System.out.println("C");
}
}
public class Main1 extends A
{
public static void main(String[] args)
{
A aa = new A();
A ab = new B();
A ac = new C();
B b = new B();
C ca = new C();
//输出:A,B,C,B,C
aa.test();
ab.test();
ac.test();
b.test();
ca.test();
}
}
对应javap为:
invokevirtual(调用实例方法)指令执行的第一步就是在运行期确定接收者的实际类型,根据实际类型进行方法调用;
4、单分派与多分派:Java是一门静态多分派,动态单分派的语言;