方法重载与invokevirtual字节码指令的关系
- 五个指令:
- ① invokeinterface:调用接口中的方法,实际上是在运行期决定的,决定到底调用实现该接口的哪个对象的特定方法。
- ② invokestatic:调用静态方法。
- ③ invokespecial:调用自己的私有方法、构造方法()以及父类方法。
- ④ invokevirtual:调用虚方法,运行期动态查找的过程。
- ⑤ invokedynamic:动态调用方法。
- 静态解析的四种情形:
- ① 静态方法
- ② 父类方法
- ③ 构造方法
- ④ 私有方法[无法被重写](公有方法不行,因为共有方法可以被override或者复写,则存在多态的可能)
- 以上四类方法称为非虚方法,他们是在类加载阶段就可以将符号引用转换为直接引用。
- ②invokestatic:
- 方法的静态分派:
- Grandpa g1 = new Father();
以上代码,g1的静态类型是Grandpa,而g1的实际类型(真正执行的类型)是Father。
我们可以得出这样一个结论:变量的静态类型是不会发生变化的,而变量的实际类型则是可以发生变化的(多态的一种体现),实际类型是在运行期方可确定。 -
//★★方法重载 是一种静态行为,编译器就可以完全确定★★ //当myTest5.test(g1);myTest5.test(g2);调用test()方法,传入g1、g2的时候,实际上会根据g1、g2的静态类型到test()的三个重载方法中进行匹配,最终所匹配的是Grandpa类型 public class MyTest5 { private void test(Grandpa grandpa){ System.out.println("grandpa"); } private void test(Father father){ System.out.println("father"); } private void test(Son son){ System.out.println("son"); } public static void main(String[] args) { Grandpa g1 = new Father(); Grandpa g2 = new Son(); MyTest5 myTest5 = new MyTest5(); myTest5.test(g1); myTest5.test(g2); } } class Grandpa{} class Father extends Grandpa{} class Son extends Father{} 运行结果: grandpa grandpa
- Grandpa g1 = new Father();