任何人都可以向我解释注释如何在java内部工作?
我知道如何通过在java中使用java.lang.annotation库来创建自定义注释.但我仍然没有得到它在内部的工作方式,例如@Override注释.
如果有人能详细解释,我将非常感激.
chr*_*ke- 124
注释类型之间的第一个主要区别是它们是在编译时使用然后丢弃(如@Override)还是放在已编译的类文件中并在运行时可用(如Spring @Component).这由注释的@Retention策略决定.如果您正在编写自己的注释,则需要确定注释在运行时是否有用(可能是自动配置),还是仅在编译时(用于检查或代码生成).
在使用注释编译代码时,编译器会看到注释,就像它在源元素上看到其他修饰符一样,例如访问修饰符(public/ private)或final.当它遇到注释时,它会运行一个注释处理器,就像一个插件类,它说它对特定的注释很感兴趣.注释处理器通常使用Reflection API来检查正在编译的元素,并且可以简单地对它们运行检查,修改它们或生成要编译的新代码.@Override是第一个例子; 它使用Reflection API来确保它可以在其中一个超类中找到方法签名的匹配项,Messager如果不能,则使用它来导致编译错误.
有很多关于编写注释处理器的教程; 这是一个有用的.期待通过对这些方法的Processor接口对于编译器是如何调用注释处理器; 主要操作发生在process方法中,每次编译器看到具有匹配注释的元素时都会调用该方法.
Eug*_*ene 32
除了别人的建议,我建议您从头开始编写自定义注释及其处理器,以了解注释的工作原理.
例如,我自己编写了一个注释来检查方法是否在编译时被重载.
首先,创建一个名为的注释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 {
}
Run Code Online (Sandbox Code Playgroud)
接下来,创建相应的处理器以处理由定义的注释注释的元素.对于带注释的方法@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;
}
}
Run Code Online (Sandbox Code Playgroud)
将注释及其进程打包到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(){
}
}
Run Code Online (Sandbox Code Playgroud)
由于nonOverloadedMethod()实际上没有超载,我们将获得如下输出:
这是@Override:http : //www.docjar.com/html/api/java/lang/Override.java.html。
它与您自己编写的注释没有什么特别之处。有趣的部分在注释的消费者中。对于像 那样的注释@Override,它可以在 Java 编译器本身、静态代码分析工具或您的 IDE 中。