为什么Java的8适用于不同的注解,派生类? [英] Why does Java 8 apply annotations differently to derived classes?
问题描述
如果我有以下两类:
// 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派生
。如果我使用的Java 7,我得到
I then compile them with javac Base.java Derived.java
and then use javap -v Derived
. If I use Java 7, I get
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, locals=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,我反而获得
If I do the same thing with Java 8, I instead get
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, 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);
descriptor: (Ljava/lang/Number;)V
flags:
Code:
stack=0, locals=2, 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, ACC_SYNTHETIC
Code:
stack=2, locals=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
RuntimeVisibleAnnotations:
0: #14()
}
Signature: #17 // LBase<Ljava/lang/Number;>;
SourceFile: "Derived.java"
这里要注意的一点是,上有无效的方法(java.lang.Object)中的在Java 8版本
存根可见的注释,是不是present在Java 7的版本。这不只是的javap
犯了一个错误 - 如果你使用反射来检查在运行时的批注present,在Java 7的版本只对<$ C $注解C>无效的方法(java.lang.Number中)和Java 8版本有它两个。这是怎么回事?
The thing to note here is that there is an annotation visible on the void method(java.lang.Object)
stub in the Java 8 version that is not present in the Java 7 version. It's not just javap
making a mistake -- if you use reflection to check the annotations present at runtime, the Java 7 version only has an annotation on void method(java.lang.Number)
and the Java 8 version has it on both. What's going on?
推荐答案
这是因为它被固定为这种行为似乎更加一致。详情请参阅 JDK-6695379 问题。而这不仅是Java的8,也有人反向移植到Java 7u80:
That's because it was fixed as this behavior seems to be more consistent. See the JDK-6695379 issue for details. And that's not only Java 8, it was also backported to 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()
这篇关于为什么Java的8适用于不同的注解,派生类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!