为什么使用invokevirtual操作码调用Java中的最终方法

des*_*nth 5 java

java中的final方法不能被继承的类覆盖。

但是,为什么使用invokevirtual而不是调用最终方法invokespecial

小智 4

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

JavaSE7 规范的链接 关于关键字的一些其他示例final

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

当我们调用final方法时,对应的字节码指令是INVOKEVIRTUAL,与其他非final方法相同。

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

CounterPoint.java

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

}
Run Code Online (Sandbox Code Playgroud)

CounterPoint 的字节码

// 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
}
Run Code Online (Sandbox Code Playgroud)

原子整数.java

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;
    }
}
Run Code Online (Sandbox Code Playgroud)