Java中expecial_JVM方法调用(invokevirtual)

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

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

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

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方法了,肯定只有这样的调用了)

下面给出我自己的理解,不知道对不对!

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

1:我在MyEclipse中用提示键得到如下,可以看出只有父类的两个方法,并没有子类Son的方法。

1adb94c89ed96c5142039fcecb806ab4.png

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

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想到的,不知道对不对,如果谁能解开我的这个疑惑真是会十分感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值