自定义注解

注解(Annotation)也被称为元数据,是JDK1.5开始引入的一个非常有用的特性。注解用来对类、接口、字段、方法等元素进行说明,可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。

注解是一个接口,它以标签的形式存在于代码中,只是作为标识存在,而不会直接影响到程序的语义;程序可以通过反射来获取指定元素的Annotation对象,然后通过Annotation对象来获取注解里面的元数据,并进行相关的操作。


1、定义

注解与类、接口、枚举处于同一层级,跟定义类使用class关键字、定义枚举使用enum关键字类似,注解使用@interface关键字进行定义

public @interface 自定义注解名称 {
}

以JDK内置系统注解@Override为例,@Override的作用是执行基本的编译时检查,用于限定重写父类方法。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

我们能看到@Override除了使用@interface进行定义之外,还使用到了元注解

元注解

用来描述数据的数据我们称之为元数据,那么元注解就是对其他注解进行标注的注解。元注解由Java API提供,是专门用于定义注解的注解,一共有四个

类型说明
@Target用于指定注解可以被用于什么地方,可用的值由ElementType进行定义。注意,注解没有明确指定Target值时可以被用于任何元素上
@Retention注解的保留策略,表示需要在什么级别保存该注解信息,由RetentionPolicy枚举定义。未指定Retention值时默认是CLASS
@Documented表示注解会被包含在Java API文档中
@Inherited允许子类继承父类的注解

ElementType

TYPE:类、接口(包括注解类型)、enum声明
FIELD:属性声明 (不包括enum实例)
METHOD:方法声明
PARAMETER:参数声明
CONSTRUCTOR:构造器声明
LOCAL_VARIABLE:局部变量声明
ANNOTATION_TYPE:注解类型声明
PACKAGE:包声明
TYPE_PARAMETER:类型参数声明(1.8新增)
TYPE_USE:类型使用声明(1.8新增)

RetentionPolicy

SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)

CLASS:注解在class文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机(JVM)中)

RUNTIME:运行期也保留注解信息,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息)

示例

定义一个可以用在类、接口、枚举上的自定义注解,该注解后期需要用来演示解析操作(需要反射机制能够读取注解信息),所以在运行期也需要保留

/**
 * 自定义注解
 */
@Target( ElementType.TYPE)
@Retention( RetentionPolicy.RUNTIME)
public @interface CustomClassAnnotation {
}

除了注解名称、可用范围、保留级别之外,很多时候我们还需要注解附加一些属性,以便进一步对数据进行描述

需要注意的是,注解的属性类型只允许是基本数据类型、String、Enum、Annotation以及Class

/**
 * 自定义类注解
 */
@Target( ElementType.TYPE)
@Retention( RetentionPolicy.RUNTIME)
@Documented
public @interface CustomClassAnnotation {
    String name() default "";
}

/**
 * 自定义属性注解
 */
@Target( ElementType.FIELD)
@Retention( RetentionPolicy.RUNTIME)
@Documented
public @interface CustomFiledAnnotation {
    String name() default "";
    long length();
    CUSTOMTYPE type() default CUSTOMTYPE.VARCHAR;
}

/**
 * 自定义注解属性type的可选值
 */
public enum CUSTOMTYPE {
    VARCHAR, 
    BIGINT
}

2、使用

自定义注解的使用跟系统内置注解使用方式一致,注解的属性值如果有默认值可以不进行赋值

@CustomClassAnnotation( name = "customClass")
public class CustomTest {

    @Column( name = "customField", type= CUSTOMTYPE.VARCHAR, length = 255)
    private String field;

}

3、访问

注解本身是没有任何效果的,单纯的使用注解并不比注释更有用处。所以在自定义注解的过程中,很重要的一部分就是创建用于对注解进行处理的逻辑。JDK1.5扩展了反射机制API,在 java.lang.reflect 包下新增了Annotation相关接口,以便读取运行时Annotation信息

相关的方法可以自行查看API文档,这里我们直接上示例

Class<?> ct = CustomTest.class;

// 获取类上指定类型的注解CustomClassAnnotation
CustomClassAnnotation[] ccas = ct.getAnnotationsByType( CustomClassAnnotation.class);
if( ccas != null && ccas.length > 0){
  CustomClassAnnotation cca = ccas[0];

  String name = cca.name();
}

// 获取类上所有注解
Annotation[] ans = ct.getAnnotations();
for( Annotation an : ans){
  // 判断是否CustomClassAnnotation注解
  if( an instanceof CustomClassAnnotation){

  }
}


Field[] fields = ct.getDeclaredFields();
if( fields != null && fields.length > 0){
  for( Field field : fields){
    // 获取属性上指定注解 CustomFiledAnnotation
    CustomFiledAnnotation[] cfa = field.getAnnotationsByType( CustomFiledAnnotation.class);
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值