第二个元注解: @Retention 参数 RetentionPolicy。有了前面的经验这个注解理解起来就简单多了,并且幸运的是这个注解还没有特殊的属性值。 简单演示下如何使用:

java 获取入参类的注解 java获取方法上的注解_类方法

java 获取入参类的注解 java获取方法上的注解_java_02

package com.tmser.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
/* 
 * 定义注解 Test 
 * 首先使用ElementType.TYPE
 * 运行级别定为 运行时,以便后面测试解析
 */ 
@Target(ElementType.PACKAGE)


    @Retention(RetentionPolicy.RUNTIME)

public @interface TestA {

}

View Code

第三和第四个元注解就不再举例了。比较简单,也没有值,相信看过上面的解释也就清楚了。下面我们还是继续来深入的探讨下注解的使用。上面的例子都非常简单,注解连属性都没有。ok,下面我们就来定义一个有属性的注解,并在例子程序中获取都注解中定义的值。

开始之前将下定义属性的规则:

@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

代码:

java 获取入参类的注解 java获取方法上的注解_类方法

java 获取入参类的注解 java获取方法上的注解_java_02

/* 
 * 定义注解 Test 
 * 为方便测试:注解目标为类 方法,属性及构造方法 
 * 注解中含有三个元素 id ,name和 gid; 
 * id 元素 有默认值 0
 */ 
@Target({TYPE,METHOD,FIELD,CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestA {
    String name();
    int id() default 0;
    Class<Long> gid();
}

View Code

下面改下我们的测试类:

java 获取入参类的注解 java获取方法上的注解_类方法

java 获取入参类的注解 java获取方法上的注解_java_02

package com.tmser.annotation;

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){ 
        
    }
}

View Code

下面到了最重要的一步了,就是如何读取我们在类中定义的注解。只要读取出来了使用的话就简单了。

jdk1.5 既然增加了注解,肯定就增加了相关读取的api

在java.lang.reflect包中新增了AnnotatedElement接口,JDK源码如下:

 

java 获取入参类的注解 java获取方法上的注解_类方法

java 获取入参类的注解 java获取方法上的注解_java_02

public interface AnnotatedElement {
        boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
        <T extends Annotation> T getAnnotation(Class<T> annotationClass);
        Annotation[] getAnnotations();
        Annotation[] getDeclaredAnnotations();
}

View Code

 

  • isAnnotationPresent:判断是否标注了指定注解
  • getAnnotation:获取指定注解,没有则返回null
  • getAnnotations:获取所有注解,包括继承自基类的,没有则返回长度为0的数组
  • getDeclaredAnnotations:获取自身显式标明的所有注解,没有则返回长度为0的数组

java 获取入参类的注解 java获取方法上的注解_类方法

java 获取入参类的注解 java获取方法上的注解_java_02

package com.tmser.annotation;

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.tmser.annotation.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());  
        }  
    } 
    
    /**
     * 简单打印出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();
    }
}

View Code

 

先别说话,运行:

java 获取入参类的注解 java获取方法上的注解_类方法

java 获取入参类的注解 java获取方法上的注解_java_02

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.tmser.annotation.UserAnnotation ; id = 2 ; description = construct; gid= class java.lang.Long

View Code

看到了吧,我们定义的注解都完整的输出了,你要使用哪个,直接拿去用就好了。

为了不让这篇文章打开太慢,我省略了类属性注解,及参数注解的解析。其实都大同小异。

另外,我也没有举使用例子。因为我认为好的教程是讲的详细的同时,还会留有扩展。如果我全部写出来,而你只是学习的话,那基本不会自己去动脑了,而是复制粘贴运行一遍完事。

  

     1. 要用好注解,必须熟悉java 的反射机制,从上面的例子可以看出,注解的解析完全依赖于反射。

     2. 不要滥用注解。平常我们编程过程很少接触和使用注解,只有做设计,且不想让设计有过多的配置时。

 疑问:

ElementType. ANNOTATION_TYPE:注解类型,到底什么作用,我发现即使不使用这个类型,我们自定义的注解也可以用来注释其他注解(eclipse 报错,但仍可以编译,也仍可以在测试类中读取出报错的注解,使用TYPE编译器都不报错),难道只是标示注解是个元注解,知道的麻烦告知一下。

(完)