java自定义注解学习

很多的类库和框架都用到了java的Annotation(注解),所以今天来学习一下怎么自定义注解。
一、Annotation的分类
1、标准注解:@Override, @Deprecated, @SuppressWarnings,这是java自带的注解
2、元注解:@Retention, @Target, @Inherited, @Documented,这是用来定义注解的注解
3、自定义注解,用元注解来自定义注解
二、元注解说明
(一)Target:定义注解的作用目标
例1:

@Target(ElementType.METHOD) //这个注解只能用在方法上
@Target({ElementType.FIELD,ElementType.METHOD})//这个注解只能用在属性和方法上

未定义Target则表示可以随便用在哪儿
(二)Retention:定义注解的保留策略
例如:

@Retention(RetentionPolicy.SOURCE)//编译前解析,注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS)// 编译时解析,默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
@Retention(RetentionPolicy.RUNTIME)// 运行时解析,注解会在class字节码文件中存在,在运行时可以通过反射获取到

(三)Documented :是否会保存到 Javadoc 文档中

@Documented

(四)Inherited:父类的注解能否被子类继承

@Inherited

三、自定义注解方式
下面定义一个可以用在属性和方法上的注解,标注了这个注解之后,程序运行时会打印该属性或方法的名字,还有作者,年龄。

@Documented
@Retention(RetentionPolicy.RUNTIME)//运行时解析
@Target({ElementType.FIELD,ElementType.METHOD})//可以用在属性和方法上
@Inherited
public @interface PrintInfo
{
    String author() default "未定义";
    int age() default -1;
}

上面的author和age都是方法名,注解的方法定义有以下规则
a. 所有方法没有方法体,没有参数没有修饰符,实际只允许 public & abstract 修饰符,默认为 public,不允许抛异常
b. 方法返回值只能是基本类型,String, Class, annotation, enumeration 或者是他们的一维数组
c. 若只有一个默认属性,可直接用 value() 函数。一个属性都没有表示该 Annotation 为 Mark Annotation
d.方法后面default是默认返回值
下面使用一下这个注解:

public class Person
{
    @PrintInfo(author = "zsj",age = 22)
    private String name;
    @PrintInfo(author = "jsz",age = 33)
    public String getName()
    {
        return name;
    }
}

四、注解的解析
注解的解析就是对注解的处理,注解的解析有两种方式,一是编译时的注解解析,二是运行时的注解解析。
编译时的注解解析是编译器自动进行的,他会查找所有继承自 AbstractProcessor 的类,然后调用他们的 process 方法去处理注解,但是我没有成功,下面是错误的例子……仅供参考

@SupportedAnnotationTypes(
{ "annotation.PrintInfo" })
public class PrintInfoProcessor extends AbstractProcessor
{
    @Override
    public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv)
    {
        //annotations是PrintInfo支持的所有元素类型集合
        for (TypeElement te : annotations)
        {
            //这里得到的是te类型的所有被PrintInfo注解过的元素
            Set<? extends Element> elementSet = roundEnv
                    .getElementsAnnotatedWith(te);
            for (Element e : elementSet)
            {
                Main.println(e.getSimpleName());
            }
        }
        return true;
    }
}

运行时注解的解析是通过反射来实现的,这个我倒是成功了:

    public static void main(String[] args)
    {
        try
        {
            Class<?> personClass = Class.forName("annotation.Person");
            Field[] fields = personClass.getDeclaredFields();
            Method[] methods = personClass.getDeclaredMethods();
            for(Field field:fields)
            {
                PrintInfo printInfo = field.getAnnotation(PrintInfo.class);
                if(printInfo != null)
                    println("作者是"+printInfo.author()
                            +"年龄是"+printInfo.age()
                            +"属性名:"+field.getName());
            }
            for(Method m:methods)
            {
                PrintInfo printInfo = m.getAnnotation(PrintInfo.class);
                if(printInfo != null)
                    println("作者是"+printInfo.author()
                            +"年龄是"+printInfo.age()
                            +"方法名"+m.getName());
            }
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }

运行的结果:

作者是zsj年龄是22属性名:name
作者是jsz年龄是33方法名getName

编译时解析的注解没有定义成功,我也不知道是什么原因,以后弄懂了再回来修改这篇博客~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值