java注解中的直接呈现、间接呈现、呈现、关联如何理解?
How to understand directly present, indirectly present, present, and associated in java annotation?
在 AnnotatedElement 的 java 文档中,我读到了术语:直接存在、间接存在、存在和关联,但我不能理解他们的意思。
例如,在文档中它说:
An annotation A is directly present on an element E if E has a RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations or RuntimeVisibleTypeAnnotations attribute, and the attribute contains A.
但我不知道 RuntimeVisibleAnnotations 属性 是什么以及“该属性包含 A”是什么意思。
谁能举一些例子来说明他们的区别,谢谢!
属性(例如RuntimeVisibleAnnotations
)
提到的属性是 class 文件格式的一部分。例如,RuntimeVisibleAnnotaitons
属性描述为 §4.7.16 of the Java Virtual Machine Specification:
The RuntimeVisibleAnnotations
attribute is a variable-length attribute in the attributes table of a ClassFile
, field_info
, or method_info
structure (§4.1,§4.5, §4.6). The RuntimeVisibleAnnotations
attribute records run-time visible annotations on the declaration of the corresponding class, field, or method.
There may be at most one RuntimeVisibleAnnotations
attribute in the attributes table of a ClassFile
, field_info
, or method_info
structure.
[...]
您可以通过 javap
检查字节码来查看此属性。例如,这个:
@FunctionalInterface // has runtime retention
public interface Foo {
void bar(); // satisfy functional interface requirements
}
给出这个:
public interface Foo
minor version: 0
major version: 58
flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
this_class: #1 // Foo
super_class: #3 // java/lang/Object
interfaces: 0, fields: 0, methods: 1, attributes: 2
Constant pool:
#1 = Class #2 // Foo
#2 = Utf8 Foo
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 bar
#6 = Utf8 ()V
#7 = Utf8 SourceFile
#8 = Utf8 Foo.java
#9 = Utf8 RuntimeVisibleAnnotations
#10 = Utf8 Ljava/lang/FunctionalInterface;
{
public abstract void bar();
descriptor: ()V
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
}
SourceFile: "Foo.java"
RuntimeVisibleAnnotations:
0: #10()
java.lang.FunctionalInterface
您可以在底部看到 class(接口)Foo
的 RuntimeVisibleAnnotations
属性。该属性包含一个条目:java.lang.FunctionalInterface
。这意味着所述注释直接出现在 Foo
.
上
存在的种类
假设我们有以下注释(省略导入):
@Retention(RUNTIME)
@Inherited
public @interface Foo {}
@Retention(RUNTIME)
@Inherited
@Repeatable(BarList.class)
public @interface Bar {}
@Retention(RUNTIME)
@Inherited
public @interface BarList {
Bar[] value();
}
那么如果我们有:
@Foo
@BarList({@Bar, @Bar})
public class Parent {}
public class Child extends Parent {}
以下为真:
Foo
直接出现在 Parent
。
Foo
存在 Child
(因为它是继承的)
BarList
直接出现在 Parent
BarList
存在 Child
(因为它是继承的)
- 两个
Bar
注释 间接存在 在 Parent
上(因为它们是可重复的并且在它们的容器注释中)
- 两个
Bar
注释都与 Child
相关(因为它们是继承的、可重复的,并且在它们的容器注释中)
一些补充说明:
如果注释直接存在在E
上,那么注释也存在并且关联 与 E
如果注释 间接存在 在 E
上,则注释也 关联 E
一个注解被继承当且仅当:
- 注释类型是meta-annotated和
java.lang.annotation.Inherited
- 注解存在于祖先class(注解继承仅适用于classes,不适用于接口、方法、字段等)
当注释被继承但出现在整个 class 层次结构中的多个 class 上时,则只会找到“最新”注释(即最接近的注释查询层次结构的底部)
如果注解在classE
上存在,但注解不可继承,则注解不会被继承存在 与E
的子class相关联
可重复的注解不需要显式地放在它们对应的容器注解中。例如,上面可以使用:
@Foo
@Bar
@Bar
public class Parent {}
这两个 Bar
注释被编译器隐式包装在它们的容器注释中(即 BarList
)。这意味着两个 Bar
注释仍然 间接存在 Parent
并且 与 Child
相关联 。但是,只有 多于一个 的可重复注释才会发生这种隐式包装。因此,如果只有一个 Bar
注释,那么它将 directly present on Parent
和 present on Child
.
在 AnnotatedElement 的 java 文档中,我读到了术语:直接存在、间接存在、存在和关联,但我不能理解他们的意思。
例如,在文档中它说:
An annotation A is directly present on an element E if E has a RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations or RuntimeVisibleTypeAnnotations attribute, and the attribute contains A.
但我不知道 RuntimeVisibleAnnotations 属性 是什么以及“该属性包含 A”是什么意思。
谁能举一些例子来说明他们的区别,谢谢!
属性(例如RuntimeVisibleAnnotations
)
提到的属性是 class 文件格式的一部分。例如,RuntimeVisibleAnnotaitons
属性描述为 §4.7.16 of the Java Virtual Machine Specification:
The
RuntimeVisibleAnnotations
attribute is a variable-length attribute in the attributes table of aClassFile
,field_info
, ormethod_info
structure (§4.1,§4.5, §4.6). TheRuntimeVisibleAnnotations
attribute records run-time visible annotations on the declaration of the corresponding class, field, or method.There may be at most one
RuntimeVisibleAnnotations
attribute in the attributes table of aClassFile
,field_info
, ormethod_info
structure.[...]
您可以通过 javap
检查字节码来查看此属性。例如,这个:
@FunctionalInterface // has runtime retention
public interface Foo {
void bar(); // satisfy functional interface requirements
}
给出这个:
public interface Foo
minor version: 0
major version: 58
flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
this_class: #1 // Foo
super_class: #3 // java/lang/Object
interfaces: 0, fields: 0, methods: 1, attributes: 2
Constant pool:
#1 = Class #2 // Foo
#2 = Utf8 Foo
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 bar
#6 = Utf8 ()V
#7 = Utf8 SourceFile
#8 = Utf8 Foo.java
#9 = Utf8 RuntimeVisibleAnnotations
#10 = Utf8 Ljava/lang/FunctionalInterface;
{
public abstract void bar();
descriptor: ()V
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
}
SourceFile: "Foo.java"
RuntimeVisibleAnnotations:
0: #10()
java.lang.FunctionalInterface
您可以在底部看到 class(接口)Foo
的 RuntimeVisibleAnnotations
属性。该属性包含一个条目:java.lang.FunctionalInterface
。这意味着所述注释直接出现在 Foo
.
存在的种类
假设我们有以下注释(省略导入):
@Retention(RUNTIME)
@Inherited
public @interface Foo {}
@Retention(RUNTIME)
@Inherited
@Repeatable(BarList.class)
public @interface Bar {}
@Retention(RUNTIME)
@Inherited
public @interface BarList {
Bar[] value();
}
那么如果我们有:
@Foo
@BarList({@Bar, @Bar})
public class Parent {}
public class Child extends Parent {}
以下为真:
Foo
直接出现在Parent
。Foo
存在Child
(因为它是继承的)BarList
直接出现在Parent
BarList
存在Child
(因为它是继承的)- 两个
Bar
注释 间接存在 在Parent
上(因为它们是可重复的并且在它们的容器注释中) - 两个
Bar
注释都与Child
相关(因为它们是继承的、可重复的,并且在它们的容器注释中)
一些补充说明:
如果注释直接存在在
E
上,那么注释也存在并且关联 与E
如果注释 间接存在 在
E
上,则注释也 关联E
一个注解被继承当且仅当:
- 注释类型是meta-annotated和
java.lang.annotation.Inherited
- 注解存在于祖先class(注解继承仅适用于classes,不适用于接口、方法、字段等)
- 注释类型是meta-annotated和
当注释被继承但出现在整个 class 层次结构中的多个 class 上时,则只会找到“最新”注释(即最接近的注释查询层次结构的底部)
如果注解在class
的子class相关联E
上存在,但注解不可继承,则注解不会被继承存在 与E
可重复的注解不需要显式地放在它们对应的容器注解中。例如,上面可以使用:
@Foo @Bar @Bar public class Parent {}
这两个
Bar
注释被编译器隐式包装在它们的容器注释中(即BarList
)。这意味着两个Bar
注释仍然 间接存在Parent
并且 与Child
相关联 。但是,只有 多于一个 的可重复注释才会发生这种隐式包装。因此,如果只有一个Bar
注释,那么它将 directly present onParent
和 present onChild
.