Java - 如何创建仅适用于类型上下文的注解类型? (PURE 类型注解)
Java - How do I create an annotation type that is only applicable in type contexts? (PURE type annotation)
要创建适用于类型上下文的类型注释,除了使用 @Target(ElementType.TYPE_USE)
对注释类型进行元注释外别无他法。但是,由于 Java 设计者的错误决定,此注释也适用于声明上下文。
根据 Java SE 文档,它是这样写的:
The constant TYPE_USE
corresponds to the type contexts in JLS 4.11, as well as to two declaration contexts: type declarations (including annotation type declarations) and type parameter declarations.
For example, an annotation whose type is meta-annotated with @Target(ElementType.TYPE_USE)
may be written on the type of a field (or within the type of the field, if it is a nested, parameterized, or array type), and may also appear as a modifier for, say, a class declaration.
The TYPE_USE
constant includes type declarations and type parameter declarations as a convenience for designers of type checkers which give semantics to annotation types. For example, if the annotation type NonNull is meta-annotated with @Target(ElementType.TYPE_USE)
, then @NonNull class C {...}
could be treated by a type checker as indicating that all variables of class C
are non-null, while still allowing variables of other classes to be non-null or not non-null based on whether @NonNull
appears at the variable's declaration.
尽管如此,我相信 TYPE_USE
最初打算用于 JLS 4.11 中描述的 16 种类型上下文。但是 Java 设计者决定将其用途扩展到声明上下文。
不知:
- 当您只需向
@Target
注释添加更多元素即可扩展注释的适用性时,他们到底为什么要做出这个决定。除了“方便”之外还有什么具体原因吗?
- 如何创建仅适用于类型上下文的注解类型? (又名。纯类型注释)
关于你的第一个问题,@Sweeper 给出了原因。通常,写在类型声明上的类型注释被视为适用于该类型的每次使用。这是一个很常见的习惯用法,要求每个注释设计者都扩展 @Target
注释会很麻烦。此外,写@Target({TYPE_USE, TYPE})
会误导,因为它声明的注解既是类型注解又是声明注解,这不是设计者的目标,与设计师的目标。
这是 Java 设计的另一个优势。在字段或方法声明中,Java 将声明上的声明注释与字段类型或方法 return 类型上的类型注释区分开来。在 class 声明上编写 TYPE_USE
注释的能力提供了一种类似的方式来区分在 class 声明上编写的注释的意图和目的。
关于你的第二个问题,你可以编写一个注解处理器,当注解写在你希望禁止的位置时,它会发出错误。您已经在使用注释处理器来强制执行类型注释的语义,因此您只需要对其进行调整。
要创建适用于类型上下文的类型注释,除了使用 @Target(ElementType.TYPE_USE)
对注释类型进行元注释外别无他法。但是,由于 Java 设计者的错误决定,此注释也适用于声明上下文。
根据 Java SE 文档,它是这样写的:
The constant
TYPE_USE
corresponds to the type contexts in JLS 4.11, as well as to two declaration contexts: type declarations (including annotation type declarations) and type parameter declarations.For example, an annotation whose type is meta-annotated with
@Target(ElementType.TYPE_USE)
may be written on the type of a field (or within the type of the field, if it is a nested, parameterized, or array type), and may also appear as a modifier for, say, a class declaration.The
TYPE_USE
constant includes type declarations and type parameter declarations as a convenience for designers of type checkers which give semantics to annotation types. For example, if the annotation type NonNull is meta-annotated with@Target(ElementType.TYPE_USE)
, then@NonNull class C {...}
could be treated by a type checker as indicating that all variables of classC
are non-null, while still allowing variables of other classes to be non-null or not non-null based on whether@NonNull
appears at the variable's declaration.
尽管如此,我相信 TYPE_USE
最初打算用于 JLS 4.11 中描述的 16 种类型上下文。但是 Java 设计者决定将其用途扩展到声明上下文。
不知:
- 当您只需向
@Target
注释添加更多元素即可扩展注释的适用性时,他们到底为什么要做出这个决定。除了“方便”之外还有什么具体原因吗? - 如何创建仅适用于类型上下文的注解类型? (又名。纯类型注释)
关于你的第一个问题,@Sweeper 给出了原因。通常,写在类型声明上的类型注释被视为适用于该类型的每次使用。这是一个很常见的习惯用法,要求每个注释设计者都扩展 @Target
注释会很麻烦。此外,写@Target({TYPE_USE, TYPE})
会误导,因为它声明的注解既是类型注解又是声明注解,这不是设计者的目标,与设计师的目标。
这是 Java 设计的另一个优势。在字段或方法声明中,Java 将声明上的声明注释与字段类型或方法 return 类型上的类型注释区分开来。在 class 声明上编写 TYPE_USE
注释的能力提供了一种类似的方式来区分在 class 声明上编写的注释的意图和目的。
关于你的第二个问题,你可以编写一个注解处理器,当注解写在你希望禁止的位置时,它会发出错误。您已经在使用注释处理器来强制执行类型注释的语义,因此您只需要对其进行调整。