Java:编译阶段的运行时反射(?!)

Java: Runtime reflection in compilation phase (?!)

Element#getAnnotation(Class<A> annotationType)javadoc中表示

Note: This method is unlike others in this and related interfaces. It operates on runtime reflective information — representations of annotation types currently loaded into the VM — rather than on the representations defined by and used throughout these interfaces. Consequently, calling methods on the returned annotation object can throw many of the exceptions that can be thrown when calling methods on an annotation object returned by core reflection. This method is intended for callers that are written to operate on a known, fixed set of annotation types.

然而,这种方法经常用于注释处理,这是编译阶段的一部分。我想了解的是在编译时将什么、如何以及为什么加载到 VM,以及优缺点。

例如,在 Element#getAnnotation(Class<A> annotationType) 的情况下,与我们得到相同的情况相比,是否有任何缺点(除了可能无法访问注释中类型 class 的值)使用镜像的信息(通常是较长的代码)?

javac 编译器应该是一个 JVM 应用程序(如果只是因为 javax.lang.model 是 Java-based API)。所以它可以在执行期间自然地使用运行时反射。

文档试图说的是——也许有点笨拙——JVM 编译器不应该加载它从源代码(或其二进制编译依赖项)构建的 类。但是当你使用 Element#getAnnotation(Class<A> annotationType) 时,它可能必须。

您引用的文档实际上列出了几个异常类,可能因此而抛出:

  1. 镜像类型异常。正如您已经意识到的那样,当您尝试加载尚未构建的类型并用作注释中的参数时会抛出它。
  2. AnnotationTypeMismatchException、EnumConstantNotPresentException 和 IncompleteAnnotationException。 javac加载的annotation版本与build classpath引用的版本不匹配时出现的那些异常can be thrown

不匹配的版本很难避免,因为一些构建系统,例如来自其余依赖项的 Gradle、require you to specify annotation processor separately