天天看点

JAVA:浅谈自定义注解

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。

Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。

自定义注解:

1.自定义注解需要使用 @interface 来开发,类似于开发一个接口

//声明一个名字为Note的注解
public @interface Note {
}
           

2.自定义注解,需要使用元注解来声明自定义注解的特性

2.1 @Target

用来声明注解可以放在什么位置,如果不写,则可以用在任何位置

ElementType.ANNOTATION_TYPE:———用在注解

ElementType.CONSTRUCTOR:—————用在构造函数

ElementType.FIELD:—————————字段、枚举的常量

ElementType.LOCAL_VARIABLE:———局部变量

ElementType.METHOD ———————方法

ElementType.PACKA————————包

ElementType.PARAMETER:————方法参数

ElementType.TYPE: ———————接口、类、枚举、注解

/*声明一个只能在方法前使用的注解*/
@Target({ElementType.METHOD})
@interface Note {
}
           

2.2 @Retention 用来声明被修饰的注解会被保留到什么阶段

可以在该注解的属性中,通过RetentionPolicy类型的值来指定注解被保留到何时。

a.RetentionPolicy.SOURCE

此注解会保留到源码阶段(.java文件)中在编译过程中被删除。

这种类型的注解通常是为了在编译时给出提示。

b.RetentionPolicy.CLASS

此注解将会被保留到源码阶段和编译阶段(.java文件和.class文件)中,在类加载过程中被删除。

这种类型的注解通常是为了提供给类加载器用。

c.RetentionPolicy.RUNTIME

此类注解会被保留在源码阶段(.java文件)、编译阶段(.class文件)、运行阶段(内存中的字节码)中。

这种类型的注解通常用来运行时提供程序的控制,一般用于反射机制控制程序的运行过程。

也只有RUNTIME级别的注解才能通过反射技术完成反射相关的操作,Spring框架大量使用了该技术。

//定义一个可以用于反射的注解
@Retention(RetentionPolicy.RUNTIME)
@interface Note {
}
           

2.3 @Documented

用来声明被修饰的注解是否要被文档提取工具提取当文档中。

默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了@Documented,则它会被 javadoc 之类的工具处理

//当使用javadoc命令生成可读文档的时候,该注解会出现在文档中
@Documented
@interface Note {
}
           

2.4 @Inherited被修饰的注解具有继承性

默认没有继承性,当使用了该标签之后,被注解标记的类将自动继承该注解中的方法。

由于要继承,所以要使用@Inherited修饰前,需要使用@Retention(RetentionPolicy.RUNTIME)修饰,只有这样文件才能完成反射传值,如果不使用反射传值,则不需要@Retention(RetentionPolicy.RUNTIME)修饰

//定义一个可以被反射注解
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedTest {
    String value();
}
           

使用上面自定义的注解修饰一个新的类,并且通过注解为新的类添加说明

@InheritedTest(value = "Ben从注解中获得的值")
public class Ben {
}
           

由于被@Inherited被修饰的注解是否具有继承性,所以Ben的子类也会有Ben的说明

//BenSong这个类继承了Ben类,那么BenSon中就应该含有Ben从注解中获得的值
public class BenSon extends Ben{
}
           

测试一下继承属性是否存在,这里用了反射方式

public static void main(String[] args) {
        Class<BenSon> benSonClass = BenSon.class;
        //判断BenSon是否继承了Ben类中的注解
        if (benSonClass.isAnnotationPresent(InheritedTest.class)){
            //如果继承了注解,则输出注解中的类容。
            System.out.println(benSonClass.getAnnotation(InheritedTest.class).value());
        }
    }
           

得到的结果:成功输出了父类Ben中的值,得到结论@Inherited被修饰的注解具有继承性

JAVA:浅谈自定义注解