Java - How do I create an annotation type that is only applicable in type contexts? (PURE type annotation)

自作多情 提交于 2020-05-28 09:36:10

问题


To create a type annotation that is applicable in type contexts, there is no way other than meta-annotating the annotation type with @Target(ElementType.TYPE_USE). However, this annotation also becomes applicable in declaration contexts due to the bad decision of the Java designers.

According to the Java SE documentation, it reads:

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.

Nonetheless, I believe TYPE_USE was originally intended to be used in 16 type contexts as described in JLS 4.11. But the Java designers made a decision to extend its usage to declaration contexts.

I wonder:

  • WHY on earth did they make this decision when you can expand an annotation's applicability simply by adding more elements to the @Target annotation. Any specific reason other than "convenience"?
  • HOW can I create an annotation type that is ONLY applicable in type contexts? (aka. Pure type annotation)

回答1:


Regarding your first question, @Sweeper gave the reason. Conventionally a type annotation written on a type declaration is treated as applying to every use of the type. This is such a common idiom that it would be troublesome to require every annotation designer to expand the @Target annotation. Furthermore, writing @Target({TYPE_USE, TYPE}) would be misleading, because it declares an annotation that is both a type annotation and a declaration annotation, which is not the designer's goal and has a different meaning than the designer's goal.

Here is another advantage to the Java design. In a field or method declaration, Java distinguishes declaration annotations on the declaration from type annotations on the field type or method return type. The ability to write a TYPE_USE annotation on a class declaration gives a similar way to distinguish the intent and purpose of annotations written on class declarations.

Regarding your second question, you can write an annotation processor that issues an error when an annotation in written at a location that you wish to prohibit. You are already using an annotation processor to enforce the semantics of type annotations, so you just need to tweak it.



来源:https://stackoverflow.com/questions/61926215/java-how-do-i-create-an-annotation-type-that-is-only-applicable-in-type-contex

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!