如果我有以下两个类:
// Base.java public abstract class Base<T> { abstract void method(T t); }
和
// Derived.java public class Derived extends Base<Number> { @Deprecated void method(Number n) {} }
然后我使用javac Base.java Derived.java编译它们,然后使用javap -v Derived.如果我使用Java 7,我得到
public class Derived extends Base<java.lang.Number> Signature: #17 // LBase<Ljava/lang/Number;>; SourceFile: "Derived.java" minor version: 0 major version: 51 flags: ACC_PUBLIC,ACC_SUPER Constant pool: #1 = Methodref #5.#20 // Base."<init>":()V #2 = Class #21 // java/lang/Number #3 = Methodref #4.#22 // Derived.method:(Ljava/lang/Number;)V #4 = Class #23 // Derived #5 = Class #24 // Base #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 method #11 = Utf8 (Ljava/lang/Number;)V #12 = Utf8 Deprecated #13 = Utf8 RuntimeVisibleAnnotations #14 = Utf8 Ljava/lang/Deprecated; #15 = Utf8 (Ljava/lang/Object;)V #16 = Utf8 Signature #17 = Utf8 LBase<Ljava/lang/Number;>; #18 = Utf8 SourceFile #19 = Utf8 Derived.java #20 = NameAndType #6:#7 // "<init>":()V #21 = Utf8 java/lang/Number #22 = NameAndType #10:#11 // method:(Ljava/lang/Number;)V #23 = Utf8 Derived #24 = Utf8 Base { public Derived(); flags: ACC_PUBLIC Code: stack=1,locals=1,args_size=1 0: aload_0 1: invokespecial #1 // Method Base."<init>":()V 4: return LineNumberTable: line 1: 0 void method(java.lang.Number); flags: Code: stack=0,locals=2,args_size=2 0: return LineNumberTable: line 7: 0 Deprecated: true RuntimeVisibleAnnotations: 0: #14() void method(java.lang.Object); flags: ACC_BRIDGE,ACC_SYNTHETIC Code: stack=2,args_size=2 0: aload_0 1: aload_1 2: checkcast #2 // class java/lang/Number 5: invokevirtual #3 // Method method:(Ljava/lang/Number;)V 8: return LineNumberTable: line 1: 0 }
如果我用Java 8做同样的事情,我会得到
public class Derived extends Base<java.lang.Number> minor version: 0 major version: 52 flags: ACC_PUBLIC,ACC_SUPER Constant pool: #1 = Methodref #5.#20 // Base."<init>":()V #2 = Class #21 // java/lang/Number #3 = Methodref #4.#22 // Derived.method:(Ljava/lang/Number;)V #4 = Class #23 // Derived #5 = Class #24 // Base #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 method #11 = Utf8 (Ljava/lang/Number;)V #12 = Utf8 Deprecated #13 = Utf8 RuntimeVisibleAnnotations #14 = Utf8 Ljava/lang/Deprecated; #15 = Utf8 (Ljava/lang/Object;)V #16 = Utf8 Signature #17 = Utf8 LBase<Ljava/lang/Number;>; #18 = Utf8 SourceFile #19 = Utf8 Derived.java #20 = NameAndType #6:#7 // "<init>":()V #21 = Utf8 java/lang/Number #22 = NameAndType #10:#11 // method:(Ljava/lang/Number;)V #23 = Utf8 Derived #24 = Utf8 Base { public Derived(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1,args_size=1 0: aload_0 1: invokespecial #1 // Method Base."<init>":()V 4: return LineNumberTable: line 1: 0 void method(java.lang.Number); descriptor: (Ljava/lang/Number;)V flags: Code: stack=0,args_size=2 0: return LineNumberTable: line 5: 0 Deprecated: true RuntimeVisibleAnnotations: 0: #14() void method(java.lang.Object); descriptor: (Ljava/lang/Object;)V flags: ACC_BRIDGE,args_size=2 0: aload_0 1: aload_1 2: checkcast #2 // class java/lang/Number 5: invokevirtual #3 // Method method:(Ljava/lang/Number;)V 8: return LineNumberTable: line 1: 0 RuntimeVisibleAnnotations: 0: #14() } Signature: #17 // LBase<Ljava/lang/Number;>; SourceFile: "Derived.java"
这里要注意的是,在Java 7版本中不存在的Java 8版本中的void方法(java.lang.Object)存根上有一个注释.这不仅仅是javap错误 – 如果您使用反射来检查运行时存在的注释,则Java 7版本仅在void方法(java.lang.Number)上具有注释,并且Java 8版本都具有这两个注释.这是怎么回事?
解决方法
这是因为它是固定的,因为这种行为似乎更加一致.有关详细信息,请参阅
JDK-6695379问题.而且这不仅仅是Java 8,它也被转载到Java 7u80:
C:\Test>"C:\Program Files\Java\jdk1.7.0_79\bin\javac.exe" Derived.java C:\Test>javap -v Derived.class >javac7_79 C:\Test>"C:\Program Files\Java\jdk1.7.0_80\bin\javac.exe" Derived.java C:\Test>javap -v Derived.class >javac7_80 C:\Test>diff javac7_79 javac7_80 2,3c2,3 < Last modified 18.05.2015; size 484 bytes < MD5 checksum bd5e729c8eda30f72f3dc5301fa9bfc2 --- > Last modified 18.05.2015; size 496 bytes > MD5 checksum 728d9e30b9aab2381e711b3edd008000 69a70,71 > RuntimeVisibleAnnotations: > 0: #14()