创建注释是一个相当简单的过程,尽管它受到某些规则的限制。现在我们需要弄清楚它们的实际用途是什么。
让我们回想一下我们是如何创建自己的注解的。
我们将为类和方法编写一个注释,并包含有关代码作者和版本的信息:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Info {
String author() default "Author";
String version() default "0.0";
}
这是我们注释的类:
@Info
public class MyClass1 {
@Info
public void myClassMethod() {}
}
@Info(version = "2.0")
public class MyClass2 {
@Info(author = "Anonymous")
public void myClassMethod() {}
}
@Info(author = "Anonymous", version = "2.0")
public class MyClass3 {
@Info(author = "Anonymous", version = "4.0")
public void myClassMethod() {}
}
我们如何在运行时使用这些数据?
通过使用反射从注释中提取元数据。回想一下反射是什么。反射是一种在运行时检查程序数据的机制。反射让您获得有关字段、方法、类构造函数和类的信息。
我们将使用反射来读取类中的注释并显示我们想要的信息。
我们将在main方法中从我们的类中读取数据:
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws NoSuchMethodException {
readMyClass(MyClass1.class);
readMyClass(MyClass2.class);
readMyClass(MyClass3.class);
}
static void readMyClass(Class<?> myClassObj) throws NoSuchMethodException {
System.out.println("\nClass: " + myClassObj.getName());
readAnnotation(myClassObj);
Method method = myClassObj.getMethod("myClassMethod");
readAnnotation(method);
}
static void readAnnotation(AnnotatedElement element) {
try {
System.out.println("Search for annotations in " + element.getClass().getName());
Annotation[] annotations = element.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof Info) {
final Info fileInfo = (Info) annotation;
System.out.println("Author: " + fileInfo.author());
System.out.println("Version: " + fileInfo.version());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们将我们类的一个实例传递给readMyClass方法。
然后我们可以将一个类和一个方法传递给readAnnotation方法。让我们这样做——我们将传递一个 Class 对象和一个 Method 对象。它需要一个实现AnnotatedElement接口的对象。这使我们可以从对象中获取注释列表并获取有关每个注释的信息。
请注意,我们只有在检查注解是否属于我们的注解类型后才能获取信息:if (annotation instanceof Info)。
程序输出为我们提供了来自注释的完整信息:
Class: annotation.MyClass1
在java.lang.Class中搜索注解
作者: Author
Version: 0.0
在java.lang.reflect.Method中搜索注解
作者: Author
Version: 0.0
Class: annotation.MyClass2
在java.lang中搜索注解。类
作者:Author
版本:2.0
java.lang.reflect.Method 中搜索注解
作者:Anonymous
版本:0.0
类:annotation.MyClass3
java.lang.Class 中搜索注解
作者:Anonymous
版本:2.0
java 中搜索注解。 lang.reflect.Method
作者:匿名
版本:4.0
在java.lang.Class中搜索注解
作者: Author
Version: 0.0
在java.lang.reflect.Method中搜索注解
作者: Author
Version: 0.0
Class: annotation.MyClass2
在java.lang中搜索注解。类
作者:Author
版本:2.0
java.lang.reflect.Method 中搜索注解
作者:Anonymous
版本:0.0
类:annotation.MyClass3
java.lang.Class 中搜索注解
作者:Anonymous
版本:2.0
java 中搜索注解。 lang.reflect.Method
作者:匿名
版本:4.0
因此,在反射的帮助下,我们能够提取元数据。
现在让我们看一个使用注释来改进代码的示例,包括总体上提高可读性、速度和质量。龙目岛将帮助我们解决这个问题。
Lombok 是一个编译器插件,它使用注释来隐藏大量代码并扩展语言,从而简化开发并添加一些功能。
考虑来自 Lombok 的注释示例:
@ToString | 生成toString()方法的实现,该方法由对象的完整表示组成:类名、所有字段及其值。 |
|
@EqualsAndHashCode | 生成默认使用非静态和非静态字段但可配置的equals和hashCode的实现。 | 可以在该项目的网站上找到更多详细信息。在那里您会找到一个使用@EqualsAndHashCode的示例,并且还显示了一个没有注释的标准实现。 |
@Getter / @Setter | 为私有字段生成 getter 和 setter。 |
|
@非空 | 用于在实例化对象时断言字段不为空。否则,将抛出NullPointerException 。 |
|
Lombok 有许多不太常用的有用的注解。我们已经考虑了它最简单的注解。您可以在官方网站上阅读有关该项目的更多信息。
GO TO FULL VERSION