繁体   English   中英

像@Override 这样的注释在 Java 内部如何工作?

[英]How do annotations like @Override work internally in Java?

任何人都可以向我解释注释在 Java 内部是如何工作的吗?

我知道我们如何通过在 java 中使用 java.lang.annotation 库来创建自定义注释。 但我仍然不明白它是如何在内部工作的,例如 @Override 注释。

如果有人能详细解释一下,我将非常感激。

各种注解之间的第一个主要区别是它们是在编译时使用然后丢弃(如@Override )还是放置在已编译的类文件中并在运行时可用(如 Spring 的@Component )。 这是由注释的@Retention策略决定的。 如果您正在编写自己的注释,则需要确定该注释是在运行时(可能用于自动配置)还是仅在编译时(用于检查或代码生成)有用。

当编译带有注解的代码时,编译器看到注解就像它看到源元素上的其他修饰符一样,比如访问修饰符( public / private )或final 当它遇到一个注解时,它会运行一个注解处理器,它就像一个插件类,表示它对特定的注解感兴趣。 注释处理器通常使用反射 API 来检查正在编译的元素,并且可以简单地对它们运行检查、修改它们或生成要编译的新代码。 @Override是第一个示例; 它使用反射 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()实际上并没有被重载,我们将得到如下输出:

在此处输入图片说明

这是@Overridehttp : //www.docjar.com/html/api/java/lang/Override.java.html

它与您自己编写的注释没有什么特别之处。 有趣的部分在注释的消费者中。 对于像@Override这样的注解,它会在 Java 编译器本身、静态代码分析工具或您的 IDE 中。

按照这个链接 这将为您的问题提供接近的答案。 如果我们关注Java中的注解,注解是在 Java 5 中引入的,并不是 Spring 特有的。 通常,注释允许您向类、方法或变量添加元数据。 注解可以由编译器(例如,@Override 注解)或框架(例如 spring)(例如,@Component 注解)进行解释。

此外,我正在添加更多参考。

  1. http://www.codeproject.com/Articles/272736/Understanding-Annotations-in-Java
  2. http://docs.oracle.com/javase/7/docs/api/java/lang/annotation/package-summary.html
  3. http://www.coderanch.com/how-to/java/AnnotationsExample

基本上,注释只是编译器或应用程序读取的标记。 根据它们的保留策略,它们仅在编译时可用或在运行时使用反射可读。

许多框架使用运行时保留,即它们会反射性地检查类、方法、字段等上是否存在某些注释,如果存在(或不存在)注释,则执行某些操作。 此外,注释的成员可用于传递更多信息。

甚至我也在寻找同样问题的答案。 下面的链接提供了整合的好东西来获取注释的内部。 https://dzone.com/articles/how-annotations-work-java希望有帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM