继承的类不能覆盖java中的最终方法。
但是为什么使用invokevirtual
而不是invokespecial
调用最终方法。
答案 0 :(得分:3)
final
修饰符的语义仅由字节码编译器强制执行。
The link to JavaSE7 specification
Some other samples about final
keyword.
invokespecial和invokevirtual指令之间的区别在于invokevirtual根据对象的类调用方法。 invokespecial指令用于调用实例初始化方法以及当前类的超类的私有方法和方法。
当我们调用final方法时,相应的字节码指令为INVOKEVIRTUAL
,与其他非最终方法相同。
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();
}
}
CounterPoint的ByteCode
// 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
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;
}
}