Java 自定义注解

目录

一、自定义Annotation

二、Java元注解

三、java.lang.annotation包

四、自定义Annotation的使用


一、自定义Annotation

先来看两个自定义注解java文件:

1.JZDesc.java
package sn.test.test6.annotation;

import java.lang.annotation.*;

/**
 * 自定义Annotation:JZDesc
 */

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JZDesc {
    public String value();
}
2.JZMethod.java 

 

package sn.test.test6.annotation;

import java.lang.annotation.*;

/**
 * 自定义Annotation:JZMethod
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JZMethod {
    String name();
    String sex();
    int age();
}

看到这里,你可能彻底蒙圈了,一上来就这么晦涩, 可能你有很多疑问,比如:

  1. @interface是什么意思?和interface关键字有什么关系吗?
  2.  Documented、Target、Retention 是神马东东? 
  3.  ElementType、RetentionPolicy又是啥玩意儿?

不要着急,我下面会一一解答。

首先,@interface 也是一个关键字,和interface关键字没有任何关系,仅仅说明要设计Annotation必须要指定类型为@interface

其次,为了更清楚的解释上面(2)(3)东东的作用,不得不先来看看java的几个原生注解

二、Java元注解

1.什么是元注解?

-定义:作用于注解上的注解,白话就是:这些注解操作的对象还是注解。

2.常见的元注解有哪些?

-分类:@Document ,@Target ,@Retention ,@Inherited

3.元注解用来干嘛的?

作用:
1. @Document :目的让这个Annotation类型的信息可以显示在javaAPI说明文档中,如果不添加的话,使用javadoc生成 的接口文档中将没有这个类型生成的任何信息。
2. @Target:作用是指定这个Annotation可以用在哪些元素之上,如果不指定,则是ElementType枚举值的最大范围
3. @Retention:作用是指定这个Annotation的类型信息保留的范围,如果不指定,则是RetentionPolicy枚举值的最大范围

解答了 Documented、Target、Retention 是神马? 这个疑问,那么再来看看第二个疑问:

ElementType、RetentionPolicy又是啥玩意? 要解释这两个问题,那就不得不提一个jar包:java.lang.annotation,具体往下看

三、java.lang.annotation包

java.lang.annotation包中有两个源文件:ElementType.java,RetentionPolicy.java,下面来看下这两个源文件的内容
1.ElementType.java 源文件
public enum ElementType {
    TYPE,
    FIELD,
    METHOD,
    PARAMETER,
    CONSTRUCTOR,
    LOCAL_VARIABLE,
    ANNOTATION_TYPE,
    PACKAGE
}
ElementType,一个enum类型,用来定义Annotation可以作用哪些元素上,有如下几种:
*      1:TYPE(类型), 是指可以用在Class,Interface,Enum和Annotation类型上
*      2:FIELD(属性),
*      3:METHOD(方法),
*      4:PARAMETER(参数),
*      5:CONSTRUCTOR(构造函数),
*      6:LOCAL_VARIABLE(局部变量),
*      7:ANNOTATION_TYPE,(注解)
*      8:PACKAGE(包)
2.RetentionPolicy 源文件
public enum RetentionPolicy {
    SOURCE,
    CLASS,
    RUNTIME
}
1. SOURCE-代表的是这个Annotation类型的信息只会保留在程序源码里,一旦编译过后,Annotation的信息就会消失,不会出现在.class文件中
2. CLASS-表示这个Annotation类型的信息既保留在程序源码里,又保留在编译后的.class文件中,但是执行时,不会被加载到JVM中
3. RUNTIME-表示这个Annotation类型的信息会分别保留在在源码里、编译好的.class文件中,执行时也会被加载到JVM中

经过上面的讲解,你可能大概了解上文中自定义Annotation文件 JZMethod.java 和JZDesc.java文件的大致内容,那么又有一个疑问,自己一注解{}内部定义的比如 value() 是什么?有什么要注意的地方吗吗?

public @interface JZDesc {
    public String value();//参数成员1
}

public @interface JZMethod {
    String name();//参数成员1
    String sex();//参数成员2
    int age();//参数成员3
}

首先,Annotation内部定义的是注解的参数成员,如@Resource(name="aaa",description="方法1"),那么name和description都是@Resource注解的参数成员,参数成员要指定参数的数据类型,如String,int,byte etc,并且可以用public修饰,也可以省略

其次,一般参数成员定义注意项有几点:

1. 只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型.
2. 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型,String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();value()参数成员就为String类型*      *      3.如果只有一个参数成员,最好把参数名称设为"value",后加小括号比如:String value();

ok,上面基本上全部解释了自定义java文件中包含的内容代表的含义,那么既然定义了两个注解文件:JZDesc.java、JZMethod.java,那么该如何应用呢?下面将简单介绍如何将注解作用到其他类上

四、自定义Annotation的使用

1.AnnotationUsage.java  Annotation(JZDesc、JZMethod)使用示例

package sn.test.test6.annotation;

@JZDesc("这是本教主自定义的一个注解,作用元素Class")
public class AnnotationUsage {
    @JZMethod(name = "唐僧",sex = "男",age = 20)
    public String man(){
        return "这是一个人";
    }

    @JZMethod(name = "悟空",sex = "男",age = 500)
    public String monkey(){
        return "这是一只成精的猴子";
    }

    @JZMethod(name = "沙僧",sex = "男",age = 1000)
    public String monster(){
        return "这是一个妖怪";
    }
}
2.Client.java 客户端Annotation实际测试
package sn.test.test6.annotation;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

public class Client {
    public static void main(String [] args) throws ClassNotFoundException {
        System.out.println("===开始测试了====");
        Class testClass=Class.forName("sn.test.test6.annotation.AnnotationUsage");
        Method[] methods=testClass.getMethods();
        /**
         * 1.获取作用在Class上的JZDesc类型注解
         */
        //判断JZDesc注解是否存在
        boolean flag=testClass.isAnnotationPresent(JZDesc.class);
        //存在
        if (flag){
            //获取注解-getAnnotation()
            JZDesc jzDesc=(JZDesc)testClass.getAnnotation(JZDesc.class);
            //获取参数成员
            System.out.println("JZDesc参数成员内容获取为:"+jzDesc.value());
        }
        /**
         * 2.获取作用在Method上的JZMethod类型注解
         */

        //判断哪些方法用了Name注解,如果用了,加入set中
        Set<Method> set = new HashSet<Method>();
        for(Method m:methods){
            boolean mflag=m.isAnnotationPresent(JZMethod.class);
            if (mflag){
                set.add(m);
            }
        }
        //一次输出方法注解内容
        for (Method m:set){
            JZMethod method=(JZMethod)m.getAnnotation(JZMethod.class);
            if (method.age()==20){
                System.out.println("===人类===");
            }
            else if(method.age()==500){
                System.out.println("===猴子===");
            }
            else if(method.age()>500){
                System.out.println("===妖怪===");
            }
            System.out.println("外号:"+method.name()+",性别:"+method.sex()+",岁数:"+method.age());
        }
        System.out.println("===结束====");
    }

}

结果输出:

 

截止到现在,你应该大致了解了Annotation的定义和使用了,当然java也有一些默认的Annotation类型,比如:@Override,@Deprecated,@SuppressWarnings,这里就不一一介绍了,有兴趣的话可以看看相关的资料信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章