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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18189980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:09:18  来源:igfitidea点击:

How do annotations like @Override work internally in Java?

javaannotations

提问by Chirag Dasani

Can anybody explain to me how annotations work internally in java?

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

I know how we can create custom annotations by using java.lang.annotation library in java. But I still don't get how it's working internally for example, the @Override annotation.

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

I will be really thankful if anyone could explain that in detail.

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

采纳答案by chrylis -cautiouslyoptimistic-

The first main distinction between kinds of annotation is whether they're used at compile time and then discarded (like @Override) or placed in the compiled class file and available at runtime (like Spring's @Component). This is determined by the @Retentionpolicy of the annotation. If you're writing your own annotation, you'd need to decide whether the annotation is helpful at runtime (for autoconfiguration, perhaps) or only at compile time (for checking or code generation).

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

When compiling code with annotations, the compiler sees the annotation just like it sees other modifiers on source elements, like access modifiers (public/private) or final. When it encounters an annotation, it runs an annotation processor, which is like a plug-in class that says it's interested a specific annotation. The annotation processor generally uses the Reflection API to inspect the elements being compiled and may simply run checks on them, modify them, or generate new code to be compiled. @Overrideis an example of the first; it uses the Reflection API to make sure it can find a match for the method signature in one of the superclasses and uses the Messagerto cause a compile error if it can't.

编译带有注解的代码时,编译器会看到注解,就像它看到源元素上的其他修饰符一样,如访问修饰符 ( public/ private) 或final. 当它遇到一个注解时,它会运行一个注解处理器,它就像一个插件类,表示它对特定的注解感兴趣。注释处理器通常使用反射 API 来检查正在编译的元素,并且可以简单地对它们运行检查、修改它们或生成要编译的新代码。@Override是第一个例子;它使用反射 API 来确保它可以在其中一个超类中找到方法签名的匹配项,Messager如果不能,则使用导致编译错误。

There are a number of tutorials available on writing annotation processors; here's a useful one. Look through the methods on the Processorinterfacefor how the compiler invokes an annotation processor; the main operation takes place in the processmethod, which gets called every time the compiler sees an element that has a matching annotation.

有许多关于编写注释处理器的教程;这是一个有用的。期待通过对这些方法Processor接口对于编译器是如何调用注释处理器; 主要操作发生在process方法中,每次编译器看到具有匹配注释的元素时都会调用该方法。

回答by Matt Ball

Here's @Override: http://www.docjar.com/html/api/java/lang/Override.java.html.

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

There's nothing special about it that differentiates it from an annotation you might write yourself. The interesting bits are in the consumersof the annotations. For an annotation like @Override, that would be in the Java compiler itself, or a static code analysis tool, or your IDE.

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

回答by Ruchira Gayan Ranaweera

Follow this link. This will provide close answer for your problem. If we focused on annotations in Java, Annotations were introduced in Java 5 and are not Spring specific. In general, annotations allow you to add metadata to a class, method or variable. An annotation can be interpreted by the compiler (for example, the @Override annotation) or by a framework such as spring (for example, the @Component annotation).

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

In addition I am adding more references.

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

  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
  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

回答by Thomas

Basically, annotations are just markers which are read by the compiler or the application. Depending on their retention policy they are available at compile time only or are readable at runtime using reflection.

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

Many frameworks use runtime retention, i.e. they reflectively check whether some annotations are present on a class, method, field etc. and do something if the annotation is present (or not). Additionally, members of annotations can be used to pass further information.

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

回答by Eugene

Besides what others suggested, I recommend you write a customized annotation and its processor from scratch to see how annotation works.

除了其他人的建议之外,我建议您从头开始编写自定义注释及其处理器,以了解注释的工作原理。

In my own, for example, I have written an annotation to check whether methods are overloaded in compile time.

以我自己为例,我写了一个注解来检查方法是否在编译时重载。

Firstly, create an annotation named Overload. This annotation is applied to method so I annotate it with @Target(value=ElementType.METHOD)

首先,创建一个名为 的注解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 {

}

Next, create corresponding processor to handle elements annotated by defined annotation. For method annotated by @Overload, its signature must appear more than one time. Or the error is printed.

接下来,创建相应的处理器来处理由定义的注解所注解的元素。对于由 注释的方法@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;
    }
}

After packaging annotation and its process into a jar file, create a class with @Overloadand use javac.exe to compile it.

将注解及其进程打包成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(){

    }
} 

Since nonOverloadedMethod()has not actually been overloaded, we will get the output like below:

由于nonOverloadedMethod()实际上并没有被重载,我们将得到如下输出:

enter image description here

在此处输入图片说明

回答by Kusum

Even I was looking for the answer of the same question. the below link provided the consolidated good stuff to get the inside of annotations. https://dzone.com/articles/how-annotations-work-javaHope it helps!

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