1、如何定义一个注解
在自定注解前先看看java提供的@Override是如何定义的
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
通过元注解@Target(ElementType.METHOD)
表明该注解可修饰方法,@Retention(RetentionPolicy.SOURCE)
表明该注解只保留在源码中,编译器会忽略掉,不会出现在.class字节码文件中。
下面定义一个MyAnnotation,包含一个value属性,并且演示如何通过反射获取注解的信息。
自定义注解通过@interface关键字来定义,非常类似于接口的定义
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
//声明一个属性value,并设置默认值hello,在使用注解时没有指定值就会使用这个默认值
String value() default "hello";
}
可以理解为方法的返回值类型就是属性的数据类型,方法名就是属性名。
2、提取注解信息
使用注解修饰某些程序元素之后,注解不会自己生效,必须由开发者提供相应的工具来读取并处理注解信息。从Java5开始,java.lang.reflect
包反射API提供了读取运行时注解的能力。注意:只有定义注解时使用@Retention(RetentionPolicy.RUNTIME)
修饰的的注解才能在运行时可见。
Java 5 在 java.lang.reflect包下新增了AnnotatedElement接口,这个接口的实现类主要包括
- Class: 类定义
- Constructor: 构造器定义
- Field: 类的成员变量定义
- Method: 方法的定义
- Package: 包的定义
程序可调用AnnotatedElement接口下的方法来访问注解信息,这个接口包含如下方法(jdk 1.8)。
//判断该程序元素上是否存在指定的注解,如果存在返回true,否则返回false.
default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return getAnnotation(annotationClass) != null;
}
//返回该程序元素上指定类型的注解,否则返回null
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
//返回该程序元素上的注解数组,如果没有则返回一个长度为0的数组
Annotation[] getAnnotations();
//这个方法与<T extends Annotation> T getAnnotation(Class<T> annotationClass)的功能基本相似,但是java8增加了重复注解,因此需要使用该方法获取修饰该元素的指定类型的多个注解。
default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
//返回直接修饰该程序元素的注解数组,如果没有则返回长度为0的数组
Annotation[] getDeclaredAnnotations();
//返回直接修饰该程序元素的指定类型注解的数组,如果没有则返回长度为0的数组
default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)
//该方法与default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)基本相似,但是java8增加了重复注解,因此需要使用该方法获取修饰该元素的指定类型的多个注解。
default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)
下面使用前面定义的MyAnnotation,并通过反射获取其value值
class Orange {
@MyAnnotation(value="I am an orange...")
public void info(){
System.out.println("橙子");
}
}
public class MyAnnotationTest {
public static void main(String[] args) {
try {
Annotation[] ans = Class.forName("com.jdqm.annotation.test.Orange").getMethod("info").getAnnotations();
for(Annotation an: ans) {
System.out.println(((MyAnnotation)an).value());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
打印结果
I am an orange...
这个例子中我们在使用注解的时候设置了value的值为“I am an orange…”,如果不设置的话就是使用默认的hello。