重载(编译期多态),重写(运行时多态)

匿名 (未验证) 提交于 2019-12-02 23:57:01

重载可以在编译期确定调用的方法。

在 Class 文件内部,方法的符号引用是根据方法名称参数来区分的,对编译器来说重载方法跟其他方法一样,都是不同的方法而已。

而 Java 的重载是根据静态类型来确定方法,所以可以在编译期就能指定调用的方法。

静态类型 & 实际类型:

如,SuperClass obj = new SubClass();语句中,前面的「 SuperClass 」是静态类型,后面的「 SubClass 」是实际类型

变量的静态类型是不可变的,编译时可知的,但是实际类型是运行时才能确定。

例:

public static void main(String[] args) {   B b = new B();   f(b); // b   A c = new C();   f(c); // 静态类型是A,所以输出a }  static void f(C c) { System.out.println("c"); } static void f(B b) { System.out.println("b"); } static void f(A a) { System.out.println("a"); }  static class A {} static class B extends A {} static class C extends A {}

重写在运行时根据实际类型来选择方法。

每个类在方法区有它的虚方法表,存放着各方法的实际入口地址。JVM 在执行 invokevirtual 时(final 方法除外),会从实际类型的虚方法表查询(没有会继续查询父类的虚方法表)。

类似的,invokeinterface 执行时会用到接口方法表。

方法表一般在类加载-连接阶段进行初始化,准备了类的变量初始值后,JVM 会把该类的方法表也初始化完毕。

注:invokestatic、invokespecial、final 方法,都能在编译期确定方法,所以 JVM 会在类加载-解析阶段,把这些方法的符号引用替换成直接引用。(final 方法是用 invokevirtual 执行的,因为不能被重写,所以编译时就能确定)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!