JVM引擎执行一个方法时,需要确定一个方法该执行的版本,页就是需要将字节码文件中的符号引用转换成内存中具体方法的地址。
?
符号引用
是用一个字符串表示一个方法。存储在方法区的常量池中。
?
直接引用
运行阶段才知道的方法在内存中的入口地址。
C++在编译时链接,确定直接引用。
Java是在解析阶段和运行阶段才将符号引用转换成直接引用。
?
加载(解析)阶段
将非虚方法的符号引用转换成直接引用。
?
运行阶段
将虚方法的符号引用转换成直接引用。
?
非虚方法
在运行之前就知道用哪个版本的方法。
静态方法 invokestatic
私有方法 invokespecial
构造方法 invokespecial
父类方法 invokespecial
Final方法 invokevirtual
?
虚方法
在运行时才确定执行哪个版本的方法,这里和多态对应。
invokevirtual
?
多态
?
方法重载
同一个类内,方法名,参数列表不同的多个版本的方法。
?
方法重写
父类和子类中,子类重写了父类的同名方法。当用父类声明一个变量时,调用该方法名称,不确定使用的是哪个版本的方法。
?
静态分派
依赖静态类型来确定调用版本的办法。
Class Test{
sayHallo(Human person);
?????? sayHello(Man person);
}
Human person = new Man();
sayHello(person);
调用的是Human那个方法。
?
动态分派
依赖动态类型来确定调用版本的办法。
Class Human{sayHello(){};}
Class Man extends Human{sayHello();}
Human person = new Man();
Person.sayHello();
调用的是Man中的方法。
?
这里的分派只是一个办法,并不是说只能用于虚方法,用于运行期确定方法版本。
动态分派可能是。
静态分派也可用于非虚方法。
一个方法办法的确定可能既存在重载也存在重写,静态分派,动态分派都在使用。
?
静态类型
动态类型
Human man = new Man();
原文:http://jshxwork.iteye.com/blog/2210306