JVM方法调用(invokevirtual)

  在java代码运行期间,方法间的调用能够说是最为频繁的了,那么这些方法间的调用在底层的虚拟机又作了什么事情呢?如今就让咱们揭开那道神秘的面纱。java

  JVM调用方法有五条指令,分别是invokestatic,invokespecial,invokevirtual,invokeinterface,invokedynamic。invokestatic用来调用静态方法;invokespecial用来调用私有方法,父类方法(super.),类构造器方法;invokeinterface调用接口方法;invokedynamic方法动态执行;invokevirtual调用全部虚方法,即除了以上的方法外全用invokevirtual调用。测试

  这篇文章主要是说明invokevirtual方法的调用,以一个例子来讲明。this

class Father{
	
	public void fMe(){
		System.out.println("fMe");
		fMe1();//invovespecial调用
		System.out.println(this);
		this.fMe1();//invovespecial调用
	}
	
	private void fMe1(){
		System.out.println("fMe1");
	}
}


class Son extends Father{
  public void fMe1(){
        System.out.println("sMe1");
    } } public class ThisTest{ public static void main(String[] args) { Father test = new Son(); test.fMe();//编译时指向父类中国的fMe(),在运行时因为是invokevirtual调用,所以test将变成实际类型Son,若是Son中有Fme(),就调用Son本身的,若没有就调用父类的 } }

   父类Father中有一个public方法fMe()和一个私有方法fMe1(),子类中没有对其方法覆盖,在测试类ThisTest中 Father test = new Son();,并调用fMe(),再在fMe()中调用本身的私有方法fMe1()。在如上的几个方法调用中test.fMe()是invokevirtual调用,编译时指向父类中国的fMe(),在运行时因为是invokevirtual调用,所以test将变成实际类型Son,若是Son中有fMe(),就调用Son本身的,若没有就调用父类的,此时是调用父类的;在父类中 的fMe1()是invovespecial调用。疑问(也是写这篇文章的目的):上面的this表明Son,既然是invovespecial调用,那么应该是调用Son的fMe1()才对啊,为何是调用父类的fMe1()。(虽然感受好无厘头,明明是private方法了,确定只有这样的调用了)spa

  下面给出我本身的理解,不知道对不对!blog

  上面的用this调用的时候,我以为在编译期间,this表明的是Father类,而不是Son类,正由于是这样,在用invovespecial字节码调用的时候采用在编译器就肯定好了指向父类fMe1()方法,而不是子类的方法。为了肯定我说的,我采用了两种方式去验证:1是用MyEclipse的动态提示,2是将fMe1()方法改成public,这样在字节码指invokevirtual调用的时候看是否是在运行期间改变this为实际类型Son类,便是不是去调用子类的fMe1()方法。接口

  1:我在MyEclipse中用提示键获得以下,能够看出只有父类的两个方法,并无子类Son的方法。ip

二、在我将fMe1()方法改成public后确实是调用的是子类的方法。ci

class Father{
	public void fMe(){
		System.out.println("fMe");
		this.
		fMe1();//invovespecial调用
		System.out.println(this);
		this.fMe1();//invovespecial调用
	}
	
	public void fMe1(){
		System.out.println("fMe1");
	}
}


class Son extends Father{
	public void fMe1(){
        System.out.println("sMe1");
    }
}

public class ThisTest{
	public static void main(String[] args) {
		Father test = new Son();
		test.fMe();//编译时指向父类中国的fMe(),在运行时因为是invokevirtual调用,所以test将变成实际类型Son,若是Son中有Fme(),就调用Son本身的,若没有就调用父类的
	}
}

 

   这是在看invokevirtual想到的,不知道对不对,若是谁能解开个人这个疑惑真是会十分感谢。编译器

相关文章
相关标签/搜索