有人可以向我解释注释在Java内部如何工作吗?
我知道如何通过使用Java中的java.lang.annotation库来创建自定义注释。但是我仍然不知道它在内部如何工作,例如@Override注释。
如果有人可以详细解释,我将非常感谢。
有人可以向我解释注释在Java内部如何工作吗?
我知道如何通过使用Java中的java.lang.annotation库来创建自定义注释。但是我仍然不知道它在内部如何工作,例如@Override注释。
如果有人可以详细解释,我将非常感谢。
Answers:
各种注释之间的第一个主要区别是它们是在编译时使用,然后丢弃(如@Override
)还是放在已编译的类文件中,并在运行时可用(如Spring的@Component
)。这由注释的@Retention策略确定。如果要编写自己的注释,则需要确定该注释在运行时(可能是用于自动配置)还是仅在编译时(用于检查或代码生成)有用。
在编译带有注释的代码时,编译器会看到注释,就像在源元素上看到其他修饰符一样,例如访问修饰符(public
/ private
)或final
。当遇到注释时,它将运行一个注释处理器,就像一个插件类,它对特定的注释感兴趣。注释处理器通常使用Reflection API来检查正在编译的元素,并且可以简单地对它们进行检查,修改它们或生成要编译的新代码。@Override
是第一个例子 它使用Reflection API来确保可以在其中一个超类中找到方法签名的匹配项,如果不能找到,则使用Messager
引起编译错误。
有很多关于编写注释处理器的教程。这是一个有用的。期待通过对这些方法的Processor
接口对于编译器是如何调用注释处理器; 主要操作发生在process
方法中,每次编译器看到带有匹配注释的元素时,该方法都会被调用。
除了其他建议外,我建议您从头开始编写自定义注释及其处理器,以了解注释的工作原理。
例如,我自己编写了注释,以检查方法在编译时是否重载。
首先,创建一个名为的注释Overload
。此注释应用于方法,所以我用@Target(value=ElementType.METHOD)
package gearon.customAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(value=ElementType.METHOD)
public @interface Overload {
}
接下来,创建相应的处理器以处理由定义的注释注释的元素。对于带有注释的方法@Overload
,其签名必须出现多次。或打印错误。
package gearon.customAnnotation;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
@SupportedAnnotationTypes("gearon.customAnnotation.Overload")
public class OverloadProcessor extends AbstractProcessor{
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// TODO Auto-generated method stub
HashMap<String, Integer> map = new HashMap<String, Integer>();
for(Element element : roundEnv.getElementsAnnotatedWith(Overload.class)){
String signature = element.getSimpleName().toString();
int count = map.containsKey(signature) ? map.get(signature) : 0;
map.put(signature, ++count);
}
for(Entry<String, Integer> entry: map.entrySet()){
if(entry.getValue() == 1){
processingEnv.getMessager().printMessage(Kind.ERROR, "The method which signature is " + entry.getKey() + " has not been overloaded");
}
}
return true;
}
}
将批注及其处理过程打包到jar文件中之后,使用创建一个类@Overload
并使用javac.exe对其进行编译。
import gearon.customAnnotation.Overload;
public class OverloadTest {
@Overload
public static void foo(){
}
@Overload
public static void foo(String s){
}
@Overload
public static void nonOverloadedMethod(){
}
}
由于nonOverloadedMethod()
实际上并未过载,因此我们将获得如下输出:
OverloadProcessor::process
为什么entry.getValue() == 1
?不必在父类/接口上添加注释,这样roundEnv.getElementsAnnotatedWith(Overload.class)
就不会得到父类/接口,对吗?
这是@Override
:http : //www.docjar.com/html/api/java/lang/Override.java.html。
没有什么特别的可以将它与您可能自己编写的注释区分开的。有趣的地方在注释的使用者中。对于像这样的注释@Override
,它将在Java编译器本身,静态代码分析工具或您的IDE中。
@Override
(或其他标准注释)。
点击此链接。这将为您的问题提供严密的答案。如果我们专注于中的注释Java
,则注释是Java 5中引入的,不是特定于Spring的。通常,批注允许您将元数据添加到类,方法或变量。注释可以由编译器(例如,@ Override注释)或诸如spring之类的框架(例如,@ Component注释)解释。
另外,我添加了更多参考。
甚至我也在寻找相同问题的答案。下面的链接提供了合并的好东西,可以深入注释。https://dzone.com/articles/how-annotations-work-java 希望有帮助!