java自定义注解

参考博客:https://blog.csdn.net/briblue/article/details/73824058

感觉这篇文章写得非常好,讲的很清楚明白,易于理解;例子也很不错,做个记录:

 

代码:

package com.cy.test;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 自定义注解测试类
 */
@MyAnnotation(id = 100, msg = "hello annotation")
public class TestAnnotation{

    @Check("hi")
    //相当于 @Check(value = "hi"),如果属性名是value的话,在使用注解时,该属性名可以省略
    private int a;

    @Perform
    public void testMethod(){

    }

    public static void main(String[] args) {
        //获取类上的注解
        TestAnnotation t = new TestAnnotation();
        boolean r = t.getClass().isAnnotationPresent(MyAnnotation.class);//是否应用了某个注解
        System.out.println(r);

        if(r){
            MyAnnotation a = t.getClass().getAnnotation(MyAnnotation.class);//获取Annotation对象  java.lang.annotation.Annotation是所有注解的老祖宗。
            System.out.println("id:" + a.id());
            System.out.println("msg:" + a.msg());
        }

        Annotation annotation[] = t.getClass().getAnnotations();    //获取所有注解
        for(Annotation an : annotation){
            System.out.println(an.annotationType());   //获取注解类型:interface com.cy.test.MyAnnotation
        }


        //获取成员变量上的注解
        Field fields[] = t.getClass().getDeclaredFields();
        Field fielda = null;
        for(Field f : fields){
            System.out.println(f.getName() +"," +f.getType() +"," + f.getGenericType() + "," + f.getModifiers());
            if(f.getName().equals("a")) fielda = f;
        }
        fielda.setAccessible(true);
        Check check = fielda.getAnnotation(Check.class);
        System.out.println("check value:"+check.value());


        //获取方法上的注解
        try {
            Method testMethod = t.getClass().getDeclaredMethod("testMethod");
            Annotation annotations[] = testMethod.getAnnotations();
            for(Annotation a : annotations) {
                System.out.println(a.annotationType().getSimpleName());
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }


    }
}

/**
 * 自定义的注解  类上
 * 注解在使用时必须给属性赋值,除非你使用了default关键字为属性指定了默认值。
 * 如果属性只有一个,并且属性名是value时,使用注解时value可以省略不写。
 * 如果属性是一个数组,使用注解时,数组值只有一个时,数组的大括号是可以省略的。
 */
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@interface MyAnnotation {
    int id() default 0;

    String msg() default "defaule msg";

}

/**
 * 注解  属性上
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Check {
    String value();
}

/**
 * 注解  方法上
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Perform {

}

 

console:

true
id:100
msg:hello annotation
interface com.cy.test.MyAnnotation
a,int,int,2
check value:hi
Perform

 

@Retention

Retention 的英文意为保留期的意思。当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间。

它的取值如下: 

RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。 
RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。 
RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。这意味着可以通过反射获取到这个注解的信息。

我们可以这样的方式来加深理解,@Retention 去给一张标签解释的时候,它指定了这张标签张贴的时间。@Retention 相当于给一张标签上面盖了一张时间戳,时间戳指明了标签张贴的时间周期。

 

@Target

你可以这样理解,当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。

类比到标签,原本标签是你想张贴到哪个地方就到哪个地方,但是因为 @Target 的存在,它张贴的地方就非常具体了,比如只能张贴到方法上、类上、方法参数上等等。@Target 有下面的取值

ElementType.TYPE                 作用于接口、类、枚举、注解
ElementType.FIELD                作用于属性、枚举的常量
ElementType.METHOD               作用于方法
ElementType.PARAMETER            作用于方法参数,可以给一个方法内的参数进行注解
ElementType.CONSTRUCTOR          作用于构造方法,可以给构造方法进行注解
ElementType.LOCAL_VARIABLE       作用于局部变量,可以给局部变量进行注解
ElementType.ANNOTATION_TYPE      作用于注解,可以给一个注解进行注解
ElementType.PACKAGE              作用于包,可以给一个包进行注解
ElementType.TYPE_PARAMETER       作用于泛型,即泛型方法、泛型类和泛型接口

 

@Documented

设置注解是否可以生成到帮助文档中。使用javadoc.exe工具可以从程序源代码中抽取类、方法、属性等注释形成一个源代码配套的API帮助文档,而该工具抽取时默认不包括注释内容。如果使用的注解被@Documented标注,那么该注解就能被javadoc.exe工具提取到API文档。

 

@Inherited

设置注解是否支持继承。Inherited的英文意思是继承,但是这个继承和我们平时理解的继承大同小异,一个被@Inherited注解了的注解修饰了一个父类,则它的子类也继承了父类的注解。

 

 

 

另外,上面例子代码中f.getModifiers()得到的是2,为什么?

JAVA 反射机制中,Field的getModifiers()方法返回int类型值表示该字段的修饰符。

其中,该修饰符是java.lang.reflect.Modifier的静态属性。

对应表如下:

PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
STATIC: 8
FINAL: 16
SYNCHRONIZED: 32
VOLATILE: 64
TRANSIENT: 128
NATIVE: 256
INTERFACE: 512
ABSTRACT: 1024
STRICT: 2048

 

 

 

--

posted on 2018-08-18 17:38  有点懒惰的大青年  阅读(214)  评论(0)    收藏  举报