本文主要参考:《深入理解Java虚拟机 jvm的高级特性和最佳实践》 以及 博文:http://rednaxelafx.iteye.com/blog/652719
博客先从一个简单的问题开始。
Q1:什么是静态方法,什么事实例方法?他们的区别?
众所周知的是:静态方法是用关键词static修饰的方法,而与之对应,没有static修饰的方法称之为实例方法。
区别 ①:“静态方法”的调用总是不指定某个对象实例为“接收者”,而“实例方法”则总是要以某个对象实例为“接收者”(receiver)。所以两者的调用形式为: 类.方法名 和对象.方法名。(Ps:类不是一个对象,所以他不是接受者)
②:两者在JVM上的区别:在调用类方法时,所有参数按顺序存放于被调用方法的局部变量区中的连续区域,从局部变量0开始;在调用实例方法时,局部变量0用于存放传入的该方法所属的对象实例(Java语言中的“this”),所有参数从局部变量1开始存放在局部变量区的连续区域中。简单点来说,静态的方法的参数里面没有this,而实例方面里面会隐式的传入this.
注意:有时候会看到 对象.静态方法,在这里起效果等于 该对象类.静态方法。 这里调用变量的类型上声明的静态方法的语法糖而已。
Q2:是什么虚方法,什么是非虚方法? 什么时候进行静态绑定? 什么时候进行运行时绑定?
非虚方法:指的是用static、private、final关键词修饰的词。这样划分的原因是:这三种修饰词修饰的方法在子类无法被覆写(覆写并不是指重新写了一个完全一样的方法,而且写了之后不会覆盖父类原本的方法)。
虚方法:除开非虚方法之外的都是虚方法,也就是说,Java里只有非private的成员方法是虚方法。
根据非虚方法划分的原因可以知道,调用目标总是固定的一个,所以编译器就可以确定唯一的方法,且在运行期它不会变化。.因此可以在编译期间对此方法进行绑定,否则需要进行动态绑定。
Q3:在JVM调用虚方法和非虚方法时本质区别是什么?
在JVM规定了五条方法调用字节码调用字节码指令:
invokestatic:调用静态方法
invokeespecail:调用父类方法、私有方法、实例构造器
invokevirtual:调用所有虚方法
invokeinterface:调用接口方法,会运行是确定一个调用次方法的对