为什么invokeVirtual存在时需要invokeSpecial

时间:2022-11-05 16:32:25

There are three opcodes to invoke Java methods. It is clear that invokeStatic is just for static method invocation.

有三个操作码来调用Java方法。很明显,invokeStatic仅用于静态方法调用。

As far as I know invokespecial is used when invoking constructor and private methods. So Do we need to differenticate private and public method invocation at run time? It could be invoked with same opcode say invokevirtual? Does JVM deals with private and public method definition? As far as I know public and private keywords is just needed at development phase for encapsulation?

据我所知,在调用构造函数和私有方法时使用了invokespecial。那么我们是否需要在运行时区分私有和公共方法调用?可以使用相同的操作码调用invokevirtual来调用它吗? JVM是否处理私有和公共方法定义?据我所知,在封装开发阶段只需要公共和私有关键字?

Any comments, Thanks.

任何评论,谢谢。

2 个解决方案

#1


30  

From this site

来自这个网站

The answer can be easily found if one reads the Java VM Spec carefully:

如果仔细阅读Java VM Spec,可以很容易地找到答案:

The difference between the invokespecial and the invokevirtual instructions is that invokevirtual invokes a method based on the class of the object. The invokespecial instruction is used to invoke instance initialization methods as well as private methods and methods of a superclass of the current class.

invokespecial和invokevirtual指令之间的区别在于invokevirtual基于对象的类调用方法。 invokespecial指令用于调用实例初始化方法以及当前类的超类的私有方法和方法。

In other words, invokespecial is used to call methods without concern for dynamic binding, in order to invoke the particular class’ version of a method.

换句话说,invokespecial用于调用方法而不关心动态绑定,以便调用特定类的方法版本。

#2


19  

http://www.artima.com/underthehood/invocationP.html The link above gives valuable examples clearly which addresing my question.

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();
    }
}

When you invoke main() in Subclass as defined above, it must print "Superclass's interesting method." If invokevirtual were used, it would print "Subclass's interesting method." Why? Because the virtual machine would choose the interestingMethod() to call based on the actual class of the object, which is Subclass. So it will use Subclass's interestingMethod(). On the other hand, with invokespecial the virtual machine will select the method based on the type of the reference, so Superclass's version of interestingMethod() will be invoked.

当您在上面定义的Subclass中调用main()时,它必须打印“Superclass的有趣方法”。如果使用invokevirtual,它将打印“Subclass的有趣方法”。为什么?因为虚拟机会根据对象的实际类选择interestingMethod()来调用,这是Subclass。所以它将使用Subclass的interestingMethod()。另一方面,使用invokespecial,虚拟机将根据引用的类型选择方法,因此将调用Superclass的interestingMethod()版本。

#1


30  

From this site

来自这个网站

The answer can be easily found if one reads the Java VM Spec carefully:

如果仔细阅读Java VM Spec,可以很容易地找到答案:

The difference between the invokespecial and the invokevirtual instructions is that invokevirtual invokes a method based on the class of the object. The invokespecial instruction is used to invoke instance initialization methods as well as private methods and methods of a superclass of the current class.

invokespecial和invokevirtual指令之间的区别在于invokevirtual基于对象的类调用方法。 invokespecial指令用于调用实例初始化方法以及当前类的超类的私有方法和方法。

In other words, invokespecial is used to call methods without concern for dynamic binding, in order to invoke the particular class’ version of a method.

换句话说,invokespecial用于调用方法而不关心动态绑定,以便调用特定类的方法版本。

#2


19  

http://www.artima.com/underthehood/invocationP.html The link above gives valuable examples clearly which addresing my question.

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();
    }
}

When you invoke main() in Subclass as defined above, it must print "Superclass's interesting method." If invokevirtual were used, it would print "Subclass's interesting method." Why? Because the virtual machine would choose the interestingMethod() to call based on the actual class of the object, which is Subclass. So it will use Subclass's interestingMethod(). On the other hand, with invokespecial the virtual machine will select the method based on the type of the reference, so Superclass's version of interestingMethod() will be invoked.

当您在上面定义的Subclass中调用main()时,它必须打印“Superclass的有趣方法”。如果使用invokevirtual,它将打印“Subclass的有趣方法”。为什么?因为虚拟机会根据对象的实际类选择interestingMethod()来调用,这是Subclass。所以它将使用Subclass的interestingMethod()。另一方面,使用invokespecial,虚拟机将根据引用的类型选择方法,因此将调用Superclass的interestingMethod()版本。