最近一直Jersey,发现里面有大量的注解,以前虽然看了一些,但是资料都感觉写的很复杂,今天希望通过一个例子,用最简单的方法分享一下到底什么是注解。
一、创建一个注解
package com.taobao.Test; import java.lang.annotation.*; /* * 定义注解 Test * 为方便测试:注解目标为类 方法,属性及构造方法 * 注解中含有三个元素 id ,name和 gid; * id 元素 有默认值 0 */ @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR }) @Retention(RetentionPolicy.RUNTIME) public @interface TestA { String name(); int id() default 0; Class<Long> gid(); }
大家看着可能有些不明白,没事儿,第一次都这样,可以回头在慢慢看,这里先简单解释一下:
- @Target:是声明在哪里使用,聪明的你看E文就明白差不多了吧
- @Retention:声明什么时候运行。CLASS、RUNTIME和SOURCE这三种,分别表示注解保存在类文件、JVM运行时刻和源代码中。只有当声明为RUNTIME的时候,才能够在运行时刻通过反射API来获取到注解的信息。
- @interface:用来声明一个注解
二、创建一个使用注解的类
package com.taobao.Test; import java.util.HashMap; import java.util.Map; /** * 这个类专门用来测试注解使用 * * @author tmser */ @TestA(name = "type", gid = Long.class) // 类成员注解 public class UserAnnotation { @TestA(name = "param", id = 1, gid = Long.class) // 类成员注解 private Integer age; @TestA(name = "construct", id = 2, gid = Long.class) // 构造方法注解 public UserAnnotation() { } @TestA(name = "public method", id = 3, gid = Long.class) // 类方法注解 public void a() { Map<String, String> m = new HashMap<String, String>(0); } @TestA(name = "protected method", id = 4, gid = Long.class) // 类方法注解 protected void b() { Map<String, String> m = new HashMap<String, String>(0); } @TestA(name = "private method", id = 5, gid = Long.class) // 类方法注解 private void c() { Map<String, String> m = new HashMap<String, String>(0); } public void b(Integer a) { } }
其实就是往注解里面添加参数。
三、使用注解
package com.taobao.Test; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class ParseAnnotation { /** * 简单打印出UserAnnotation 类中所使用到的类注解 该方法只打印了 Type 类型的注解 * * @throws ClassNotFoundException */ public static void parseTypeAnnotation() throws ClassNotFoundException { Class clazz = Class.forName("com.taobao.Test.UserAnnotation"); Annotation[] annotations = clazz.getAnnotations(); for (Annotation annotation : annotations) { TestA testA = (TestA) annotation; System.out.println("id= "" + testA.id() + ""; name= "" + testA.name() + ""; gid = " + testA.gid()); }
//输出 id= "0"; name= "type"; gid = class java.lang.Long } /** * 简单打印出UserAnnotation 类中所使用到的方法注解 该方法只打印了 Method 类型的注解 * * @throws ClassNotFoundException */ public static void parseMethodAnnotation() { Method[] methods = UserAnnotation.class.getDeclaredMethods(); for (Method method : methods) { /* * 判断方法中是否有指定注解类型的注解 */ boolean hasAnnotation = method.isAnnotationPresent(TestA.class); if (hasAnnotation) { /* * 根据注解类型返回方法的指定类型注解 */ TestA annotation = method.getAnnotation(TestA.class); System.out.println("method = " + method.getName() + " ; id = " + annotation.id() + " ; description = " + annotation.name() + "; gid= " + annotation.gid()); } } } /** * 简单打印出UserAnnotation 类中所使用到的方法注解 该方法只打印了 Method 类型的注解 * * @throws ClassNotFoundException */ public static void parseConstructAnnotation() { Constructor[] constructors = UserAnnotation.class.getConstructors(); for (Constructor constructor : constructors) { /* * 判断构造方法中是否有指定注解类型的注解 */ boolean hasAnnotation = constructor.isAnnotationPresent(TestA.class); if (hasAnnotation) { /* * 根据注解类型返回方法的指定类型注解 */ TestA annotation = (TestA) constructor.getAnnotation(TestA.class); System.out.println("constructor = " + constructor.getName() + " ; id = " + annotation.id() + " ; description = " + annotation.name() + "; gid= " + annotation.gid()); } } } public static void main(String[] args) throws ClassNotFoundException { parseTypeAnnotation(); parseMethodAnnotation(); parseConstructAnnotation(); } }
运行输出:
id= "0"; name= "type"; gid = class java.lang.Long method = c ; id = 5 ; description = private method; gid= class java.lang.Long method = a ; id = 3 ; description = public method; gid= class java.lang.Long method = b ; id = 4 ; description = protected method; gid= class java.lang.Long constructor = com.taobao.Test.UserAnnotation ; id = 2 ; description = construct; gid= class java.lang.Long
如果你还有疑问,想要知道为什么调用诸如:clazz.getAnnotations(); 就返回接口类型的数据,那么可以参考如下内容:
四、AnnotatedElement接口
JDK源代码如下:
public interface AnnotatedElement { boolean isAnnotationPresent(Class<? extends Annotation> annotationClass); <T extends Annotation> T getAnnotation(Class<T> annotationClass); Annotation[] getAnnotations(); Annotation[] getDeclaredAnnotations(); }
说明一下:
- isAnnotationPresent:判断是否标注了指定注解
- getAnnotation:获取指定注解,没有则返回null
- getAnnotations:获取所有注解,包括继承自基类的,没有则返回长度为0的数组
- getDeclaredAnnotations:获取自身显式标明的所有注解,没有则返回长度为0的数组