在最近一次Java开发人员的采访中,我遇到了关于spring注释的问题:
以下语言中的编译时注释和运行时注释之间有什么区别 春天吗?
有这样的概念吗?
一个答案将不胜感激。
答案 0 :(得分:1)
没有什么比编译时或运行时注释更好。
它们是读取不同API的标记。根据它们的处理方式,可以将它们称为编译/运行时注释。
Java提供了两个不同的选项来处理源代码注释。其中一个是在编译时使用的注释处理API,另一个是在运行时使用的反射API。例如@Override
注释由编译器读取。
https://ieeexplore.ieee.org/document/7321547/
有点类似于您的问题。看看它: When are Java annotations executed?
答案 1 :(得分:0)
注释是装饰类/属性或方法的通用方法。它们与编译时间或运行时无关。 但是,使用批注进行工作的类可以在编译时或运行时进行此操作。
示例: 春季AOP。对于AOP,您可以使用@Aspect批注装饰类,并根据要创建的代理类型,在编译时进行字节码修改或在运行时进行编织。 您可以通过ajc编译器/ JDK动态代理/ CGLib代理找到更多详细信息。
答案 2 :(得分:0)
通俗地说,当有人在Java中引用“编译时”或“运行时”注释时,他们很可能会引用注释的已分配(或隐含)保留策略。因此,要回答访谈问题,通常需要了解Java批注以及Spring框架定义的特定批注。关于Java,JLS 15 §9.6.4.2说:
注释只能在源代码中出现,或者它们可以以类或接口的二进制形式出现。通过Java SE Platform的反射库,以二进制形式存在的注释在运行时可能会或可能会不可用。注释类型
java.lang.annotation.Retention
用于在这些可能性中进行选择。
RetentionPolicy enum提供了三种可能性(订购我的产品):
SOURCE
-批注将被编译器丢弃。
CLASS
-注释由编译器记录在类文件中,但在运行时VM无需保留。
RUNTIME
-注释由编译器记录在类文件中,并在运行时由VM保留,因此可以通过反射方式读取。
如果您可以访问源代码,则可以访问所有注释,但是保留为SOURCE
的注释将永远不会出现在已编译的字节码中。它们永远不会出现在读取类的编译形式的任何工具上(例如,在编译下游应用程序时),并且没有字节码,运行时也不会加载任何东西。
当注释具有CLASS
保留时,注释将在使用注释的已编译字节码中存在-以便可以通过直接在字节码上操作的工具来检查其使用。示例包括编译器,代码质量工具(例如Spotbugs)或运行时代码生成器(ASM,javassist,Byte-Buddy等)。尽管注释信息存在于字节码(*.class
文件)中,但JVM 不会在运行时加载此信息。
最后,保留为RUNTIME
的注释具有上述所有功能,但也可以在运行时加载到JVM中,并且可以从运行程序中使用Reflection API进行查找。
如果未为注释明确定义保留,则默认为RetentionPolicy.CLASS
。