有三个操作码可以调用Java方法。很明显,invokeStatic只是用于静态方法调用。
据我所知,在调用构造函数和私有方法时使用了invokespecial。那么,我们需要在运行时区分私有和公共方法调用吗?它可以用同样的操作码调用,比如invokevirtual?
JVM处理私有和公共方法定义吗?据我所知,公共关键字和私有关键字只是在开发阶段需要封装吗?
发布于 2012-12-07 22:12:45
http://www.artima.com/underthehood/invocationP.html上面的链接清楚地给出了有价值的例子,解决了我的问题。
class Superclass {
private void interestingMethod() {
System.out.println("Superclass's interesting method.");
}
void exampleMethod() {
interestingMethod();
}
}
class Subclass extends Superclass {
void interestingMethod() {
System.out.println("Subclass's interesting method.");
}
public static void main(String args[]) {
Subclass me = new Subclass();
me.exampleMethod();
}
}在如上定义的子类中调用main()时,它必须打印“超类的有趣方法”。如果使用了invokevirtual,它将输出"Subclass's interesting method“。为什么?因为虚拟机将根据对象的实际类(即子类)选择要调用的interestingMethod()。因此它将使用子类的interestingMethod()。另一方面,使用invokespecial,虚拟机将根据引用的类型选择方法,因此将调用超类版本的interestingMethod()。
发布于 2012-12-07 21:46:48
如果仔细阅读
VM规范,答案很容易找到:
invokespecial和invokevirtual指令之间的区别在于,invokevirtual基于对象的类调用方法。调用专用指令用于调用实例初始化方法以及私有方法和当前类的超类的方法。换句话说,invokespecial用于调用方法,而不考虑动态绑定,以便调用方法的特定类版本。
发布于 2018-10-09 13:34:53
感谢你读出这个解释:如果它能帮助你在方法调用过程中识别汇编指令的创建,请不要忘记向上投票,我在这里解释静态绑定与动态绑定。
首先我要告诉你,invokeStatic,invokeSpecial,invokeVirtual,invokeInterface等都是编译器编译后生成的汇编指令。众所周知,编译后得到的是.class格式的文件,无法读出。但是java为命名的"javap"提供了一个工具。
我们可以使用javap命令读出我们的.class文件汇编指令。默认情况下,我们看不到私有方法汇编指令,所以我们需要对它使用-private。下面是查看java编译器生成的汇编指令的命令:
A类{ public void printValue() { System.out.println("Inside A");}
public static void callMethod(A a) { a.printValue();}}
<代码>H115您可以看到方法调用的汇编生成--> <代码>E116a.printValue();
注意:现在请记住,如果我们的调用方法是静态的,则生成invokeStatic程序集;如果它是私有的,则生成invokeSpecial程序集指令;如果它是公共的,则生成invokeVirtual指令。公共方法并不意味着每次生成invokeVirtual指令时都会生成。在super.printValue()的情况下,从A的子类调用是例外情况。也就是说,如果A是B的父类,并且B包含相同的方法printValue(),那么它将生成invokeVirtual(动态),但是如果B中的printValue()将super.printValue()作为其第一个语句,那么即使A的printValue()是公共的,也会生成invokeStatic。
让我们也试试这个:
class B extends A
{
public void printValue()
{
super.printValue();// invokeStatic
System.out.println("Inside B");
}
}
public class Test
{
public static void main(String[] arr)
{
A a = new A();
B b = new B();
A.callMethod(a);// invokeVirtual
A.callMethod(b);// invokeVirtual
}
}-->通过Test.java保存-->运行javac Test.java --> javap -c -private测试
https://stackoverflow.com/questions/13764238
复制相似问题