理解 Java 中的注解
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5685795/
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
Understanding annotation in Java
提问by Anupam Gupta
I was trying to go through some online material to learn annotation in java.
我试图通过一些在线材料来学习 Java 中的注释。
In the following code, what happened to my dear "Hello world" string which I passed in this line: @Test_Target(doTestTarget="Hello World !")
?
在下面的代码,发生了什么事我亲爱的“Hello World”的字符串,我在这行通过:@Test_Target(doTestTarget="Hello World !")
?
@Target(ElementType.METHOD)
public @interface Test_Target {
public String doTestTarget();
}
above is the annotation defined and below is its usage
上面是定义的注解,下面是它的用法
public class TestAnnotations {
@Test_Target(doTestTarget="Hello World !")
private String str;
public static void main(String arg[]) {
new TestAnnotations().doTestTarget();
}
public void doTestTarget() {
System.out.printf("Testing Target annotation");
}
}
When I run this code it is only printing Testing Target annotation
当我运行此代码时,它只是打印 Testing Target annotation
Please help me out, I am completely new to annotation.
请帮帮我,我对注释完全陌生。
回答by Luke Woodward
Annotations are basically bits of data you can attach to fields, methods, classes, etc.
注释基本上是可以附加到字段、方法、类等的数据位。
The syntax for declaring annotations in Java is a little awkward. They look a bit like interfaces (they are, after all, declared with @interface
), but they aren't really interfaces. I think you might have put the doTestTarget()
method in your TestAnnotations
class because you thought your annotation was an interface and you needed to implement it. This isn't true - you can delete this method and the call to it from your code if you wish and doing so won't cause you any problems.
在 Java 中声明注解的语法有点笨拙。它们看起来有点像接口(毕竟它们是用 声明的@interface
),但它们并不是真正的接口。我认为您可能已将该doTestTarget()
方法放入TestAnnotations
类中,因为您认为您的注释是一个接口并且您需要实现它。这不是真的 - 如果您愿意,您可以从代码中删除此方法和对它的调用,这样做不会给您带来任何问题。
Also, you might not have intended to put the annotation on the field str
. Annotations apply only to what immediately follows them. As a result, your code doesn't compile, because you've applied your annotation to a field but declared that your annotation can only be applied to methods. Change @Target(ElementType.METHOD)
to @Target(ElementType.FIELD)
and your code should then compile.
此外,您可能不打算将注释放在 field 上str
。注释仅适用于紧随其后的内容。因此,您的代码无法编译,因为您已将注释应用于字段,但声明您的注释只能应用于方法。更改@Target(ElementType.METHOD)
为@Target(ElementType.FIELD)
,然后您的代码应该可以编译。
As for what happens to the string Hello World !
, it gets written to the .class file and is available to any tool that reads in Java classes. However, it wouldn't necessarily be available in the JVM at runtime. This happens because you didn't specify a @Retention
for your @Test_Target
annotation. The default value for @Retention
is RetentionPolicy.CLASS
, which means that the JVM might not bother to load them out of the class file. (See the Javadoc for the RetentionPolicy enum.)
至于 string 会发生什么Hello World !
,它会被写入 .class 文件,并且可供任何读取 Java 类的工具使用。但是,它不一定在运行时在 JVM 中可用。发生这种情况是因为您没有@Retention
为@Test_Target
注释指定 a 。为默认值@Retention
是RetentionPolicy.CLASS
,这意味着JVM大可不必去加载出来的类文件。(有关RetentionPolicy 枚举,请参阅Javadoc。)
I imagine you want to see some way of reading the value out of this annotation at runtime. If so, I'd recommend adding @Retention(RetentionPolicy.RUNTIME)
to your annotation to make sure it will be available at runtime.
我想你想看看在运行时从这个注释中读取值的某种方式。如果是这样,我建议添加@Retention(RetentionPolicy.RUNTIME)
到您的注释中以确保它在运行时可用。
To access your annotation and the value contained within it at runtime, you need to use reflection. I've rewritten your TestAnnotations
class as follows to give a quick demonstration:
要在运行时访问您的注释和其中包含的值,您需要使用反射。TestAnnotations
为了快速演示,我已将您的类重写如下:
import java.lang.reflect.Field;
public class TestAnnotations {
@Test_Target(doTestTarget="Hello World !")
private String str;
public static void main(String[] args) throws Exception {
// We need to use getDeclaredField here since the field is private.
Field field = TestAnnotations.class.getDeclaredField("str");
Test_Target ann = field.getAnnotation(Test_Target.class);
if (ann != null) {
System.out.println(ann.doTestTarget());
}
}
}
When I run this code, it gives me the following output:
当我运行这段代码时,它给了我以下输出:
Hello World !
回答by Pa?lo Ebermann
In principle, adding an annotation by itself does not fundamentally alter the programs behaviour.
原则上,单独添加注释并不会从根本上改变程序的行为。
In your case, you created a new annotation type @Test_Target
, which can by used on any method (as indicated by its @Target
annotation).
在您的情况下,您创建了一个新的 annotation type @Test_Target
,它可以用于任何方法(如其@Target
注释所示)。
Then you applied this not to a method, but to the str
field (which should give a compiler error, I think).
然后你不是将它应用于方法,而是应用于str
领域(我认为这应该会产生编译器错误)。
Independently of this, you are creating an object with a doTestTarget
method, and invoke it, and get the expected result (i.e. the method is executed).
与此无关,您正在创建一个带有doTestTarget
方法的对象,并调用它,并获得预期的结果(即执行该方法)。
If you want your annotation to do something more than simply be there and provide some information for the reader of the source, you have to use it - either with an annotation processor at compile time, or using reflection on run time (then you would need also @Retention(RUNTIME)
as an annotation on Test_Target
.)
如果您希望您的注释做的不仅仅是在那里为源代码的读者提供一些信息,您必须使用它 - 在编译时与注释处理器一起使用,或在运行时使用反射(那么您需要也@Retention(RUNTIME)
作为注释Test_Target
。)
回答by fzonin
In the spirit of learning, another way is to use the annotated class without targeting a method or field. First declare your interface with the method you need and Retention Policy to Runtime
本着学习精神,另一种方法是使用带注释的类,而不针对方法或字段。首先使用您需要的方法和运行时的保留策略声明您的接口
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface Test_Target {
public String doTestTarget() default "default string";
}
then annotate the interface created to your class. From your class find the annotated class and then call the method with it.
然后注释为您的类创建的接口。从您的类中找到带注释的类,然后用它调用方法。
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
@Test_Target(doTestTarget="Hello World !")
public class TestAnnotations {
public static void main(String[] args) throws Exception
{
AnnotatedElement c = TestAnnotations.class;
if(c.isAnnotationPresent(Test_Target.class))
{
Annotation singleAnnotation = c.getAnnotation(Test_Target.class);
Test_Target tt = (Test_Target) singleAnnotation;
System.out.println(tt.doTestTarget());
}
}
}
}
the result is: Hello World !
结果是:你好世界!