JAVA 注解的几大作用及使用方法详解

最近一直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的数组
posted @ 2013-11-04 17:49  李秋  阅读(4316)  评论(0)    收藏  举报