首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么java中的最终方法是使用invokevirtual调用的

为什么java中的最终方法是使用invokevirtual调用的
EN

Stack Overflow用户
提问于 2018-04-03 15:13:02
回答 3查看 709关注 0票数 7

继承的类不能覆盖java中的最后方法。

但是为什么最后的方法是使用invokevirtual而不是invokespecial调用的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-04-04 07:55:34

final修饰符的语义仅由字节码编译器强制执行。

与JavaSE7规范的链接 关键词。

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

当我们调用最终方法时,相应的字节码指令是INVOKEVIRTUAL,与其他非最终方法一样。

下面是使用final关键字调用方法的示例。

CounterPoint.java

代码语言:javascript
复制
public class CounterPoint extends Point {

    private static final AtomicInteger counter = new AtomicInteger();

    public CounterPoint(int x, int y) {
        super(x, y);
        counter.incrementAndGet();
    }

    public static String numberCreated() {
        return counter.toString();
    }

}

ByteCode of CounterPoint

代码语言:javascript
复制
// class version 52.0 (52)
// access flags 0x21
public class com/xetrasu/CounterPoint extends java/awt/Point  {

  // compiled from: CounterPoint.java

  // access flags 0x1A
  private final static Ljava/util/concurrent/atomic/AtomicInteger; counter

  // access flags 0x1
  public <init>(II)V
   L0
    LINENUMBER 11 L0
    ALOAD 0
    ILOAD 1
    ILOAD 2
    INVOKESPECIAL java/awt/Point.<init> (II)V
   L1
    LINENUMBER 12 L1
    GETSTATIC com/xetrasu/CounterPoint.counter : Ljava/util/concurrent/atomic/AtomicInteger;
    INVOKEVIRTUAL java/util/concurrent/atomic/AtomicInteger.incrementAndGet ()I
    POP
   L2
    LINENUMBER 13 L2
    RETURN
   L3
    LOCALVARIABLE this Lcom/xetrasu/CounterPoint; L0 L3 0
    LOCALVARIABLE x I L0 L3 1
    LOCALVARIABLE y I L0 L3 2
    MAXSTACK = 3
    MAXLOCALS = 3

  // access flags 0x9
  public static numberCreated()Ljava/lang/String;
   L0
    LINENUMBER 16 L0
    GETSTATIC com/xetrasu/CounterPoint.counter : Ljava/util/concurrent/atomic/AtomicInteger;
    INVOKEVIRTUAL java/util/concurrent/atomic/AtomicInteger.toString ()Ljava/lang/String;
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 0

  // access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 8 L0
    NEW java/util/concurrent/atomic/AtomicInteger
    DUP
    INVOKESPECIAL java/util/concurrent/atomic/AtomicInteger.<init> ()V
    PUTSTATIC com/xetrasu/CounterPoint.counter : Ljava/util/concurrent/atomic/AtomicInteger;
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0
}

AtomicInteger.java

代码语言:javascript
复制
public class AtomicInteger extends Number implements java.io.Serializable {
    public String toString() {
        return Integer.toString(get());
    }
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }
}
票数 4
EN

Stack Overflow用户

发布于 2022-08-13 05:19:58

听起来你实际上想问的是:

为什么我们需要一个可静态链接的方法的vtable查找?

请放心,在实践中,这种查找是在链接- 至少在HotSpot里期间优化的。

事实上,最终实例方法被看作是虚拟的,而不是特殊的,这似乎是JVMS的一个技术性问题。

票数 0
EN

Stack Overflow用户

发布于 2022-08-13 05:56:23

为了在INVOKEVIRTUAL中实现二进制兼容性规则,有必要使用final方法调用JLS 13.4.17方法。

“将声明为final的方法更改为不再声明为final并不会破坏与现有二进制文件的兼容性。”

如果将对final方法的调用编译为INVOKESPECIAL,那么如果方法被更改为非final,则需要重新编译。这违反了上面的规则。

但是,正如其他答案/注释已经指出的那样,JIT编译器无论如何都会选择最佳的调用序列。即使没有将方法声明为final,JIT编译器也可以确定何时不需要vtable调度。(它甚至可以在加载使先决条件无效的新类时重新编译方法。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49633525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档