1. Overview
1.概述
In this tutorial, we’ll learn how to get a field’s annotations. Additionally, we’ll explain how the retention meta-annotation works. Afterward, we’ll show the difference between two methods that return a field’s annotations.
在本教程中,我们将学习如何获得一个字段的注释。此外,我们将解释保留元注释是如何工作的。之后,我们将展示两个返回字段注释的方法之间的区别。
2. Retention Policy of the Annotation
2.注释的保留政策
First, let’s have a look at the Retention annotation. It defines the lifecycle of an annotation. This meta-annotation takes a RetentionPolicy attribute. That is to say, the attribute defines the lifecycle where an annotation is visible:
首先,我们来看看Retention注解。它定义了一个注解的生命周期。这个元注释需要一个RetentionPolicy属性。也就是说,该属性定义了一个注释可见的生命周期。
- RetentionPolicy.SOURCE – visible only in the source code
- RetentionPolicy.CLASS – visible to the compiler at compilation time
- RetentionPolicy.RUNTIME – visible to the compiler and to the runtime
Therefore, only the RUNTIME retention policy allows us to read an annotation programmatically.
因此,只有RUNTIME保留策略允许我们以编程方式读取注释。
3. Get a Field’s Annotations Using Reflection
3.使用反射获得一个字段的注解
Now, let’s create an example class with an annotated field. We’ll define three annotations, where only two are visible at runtime.
现在,让我们创建一个带有注解字段的实例类。我们将定义三个注解,其中只有两个在运行时是可见的。
The first annotation is visible at runtime:
第一个注释在运行时是可见的。
@Retention(RetentionPolicy.RUNTIME)
public @interface FirstAnnotation {
}
A second one has the same retention:
第二个人有同样的保留。
@Retention(RetentionPolicy.RUNTIME)
public @interface SecondAnnotation {
}
Finally, let’s create a third annotation visible only in source code:
最后,让我们创建一个仅在源代码中可见的第三个注释。
@Retention(RetentionPolicy.SOURCE)
public @interface ThirdAnnotation {
}
Now, let’s define a class with a field classMember annotated with all three of our annotations:
现在,让我们定义一个带有classMember字段的类,该字段被我们所有的三个注解所注解。
public class ClassWithAnnotations {
@FirstAnnotation
@SecondAnnotation
@ThirdAnnotation
private String classMember;
}
After that, let’s retrieve all visible annotations at runtime. We’ll use Java reflection, which allows us to inspect the field’s attributes:
之后,让我们在运行时检索所有可见的注释。我们将使用Java反射,它允许我们检查字段的属性:。
@Test
public void whenCallingGetDeclaredAnnotations_thenOnlyRuntimeAnnotationsAreAvailable() throws NoSuchFieldException {
Field classMemberField = ClassWithAnnotations.class.getDeclaredField("classMember");
Annotation[] annotations = classMemberField.getDeclaredAnnotations();
assertThat(annotations).hasSize(2);
}
As a result, we retrieved only two annotations that are available at runtime. The method getDeclaredAnnotations returns an array of length zero in case no annotations are present on a field.
因此,我们只检索了两个在运行时可用的注释。方法getDeclaredAnnotations在一个字段上没有注释的情况下返回一个长度为0的数组。
We can read a superclass field’s annotations in the same way: retrieve the superclass’s field and call the same getDeclaredAnnotations method.
我们可以用同样的方法读取超类字段的注解。检索超类的字段并调用相同的getDeclaredAnnotations方法。
4. Check if Field Is Annotated With a Specific Type
4.检查字段是否有特定类型的注释
Let’s now look at how to check if a particular annotation is present on a field. The Field class has a method isAnnotationPresent that returns true when an annotation for a specified type is present on the element. Let’s test it on our classMember field:
现在让我们来看看如何检查某个字段上是否存在特定的注释。字段类有一个方法isAnnotationPresent,当元素上存在指定类型的注释时,该方法返回true。让我们在我们的classMember字段上测试一下。
@Test
public void whenCallingIsAnnotationPresent_thenOnlyRuntimeAnnotationsAreAvailable() throws NoSuchFieldException {
Field classMemberField = ClassWithAnnotations.class.getDeclaredField("classMember");
assertThat(classMemberField.isAnnotationPresent(FirstAnnotation.class)).isTrue();
assertThat(classMemberField.isAnnotationPresent(SecondAnnotation.class)).isTrue();
assertThat(classMemberField.isAnnotationPresent(ThirdAnnotation.class)).isFalse();
}
As expected, the ThirdAnnotation is not present because it has a SOURCE retention policy specified for the Retention meta-annotation.
正如预期的那样,ThirdAnnotation没有出现,因为它有一个为Retentionmeta-annotation指定的SOURCE保留策略。
5. Field Methods getAnnotations and getDeclaredAnnnotations
5.字段方法getAnnotations和getDeclaredAnnnotations
Let’s now have a look at two methods exposed by the Field class, getAnnotations and getDeclaredAnnotations. According to Javadoc, the getDeclaredAnnotations method returns annotations that are directly present on the element. On the other hand, Javadoc says for getAnnotations that it returns all annotations present on the element.
现在让我们来看看Field类所暴露的两个方法,getAnnotations和getDeclaredAnnotations。根据Javadoc,getDeclaredAnnotations 方法返回直接存在于该元素上的注释。另一方面,Javadoc对getAnnotations 说,它返回元素上存在的所有注释。
A field in a class contains annotations just above its definition. As a result, there is no inheritance of annotations involved at all. All annotations must be defined together with the field definition. Because of that, methods getAnnotations and getDeclaredAnnotations always return the same result.
一个类中的字段就在其定义之上包含注释。因此,根本不涉及注解的继承。所有的注解必须与字段定义一起定义。正因为如此,方法getAnnotations和getDeclaredAnnotations 总是返回相同的结果。
Let’s show it in a simple test:
让我们用一个简单的测试来说明。
@Test
public void whenCallingGetDeclaredAnnotationsOrGetAnnotations_thenSameAnnotationsAreReturned() throws NoSuchFieldException {
Field classMemberField = ClassWithAnnotations.class.getDeclaredField("classMember");
Annotation[] declaredAnnotations = classMemberField.getDeclaredAnnotations();
Annotation[] annotations = classMemberField.getAnnotations();
assertThat(declaredAnnotations).containsExactly(annotations);
}
Moreover, in the Field class, we can find that the getAnnotations method calls the getDeclaredAnnotations method:
此外,在Field类中,我们可以发现getAnnotations方法调用getDeclaredAnnotations方法。
@Override
public Annotation[] getAnnotations() {
return getDeclaredAnnotations();
}
6. Conclusion
6.结论
In this short article, we explained the retention policy meta-annotation role in retrieving annotations. Then we showed how to read a field’s annotations. Finally, we proved that there is no inheritance of annotations for a field.
在这篇短文中,我们解释了保留策略元注释在检索注释中的作用。然后我们展示了如何读取一个字段的注释。最后,我们证明了一个字段的注释是没有继承性的。
As always, the source code of the example is available over on GitHub.
一如既往,该示例的源代码可在GitHub上获得over。