java注解详解以及如何获取注解的上的信息

一、Java 自定义注解详解

1. 定义注解:

注解的定义很像接口的定义。事实上与其他 java 接口一样,注解也会被编译成 class 文件。定义注解时需要一些元注解。

2. 元注解介绍

@Target 详细介绍

描述
ElementType.TYPE 接口、类、枚举、注解
ElementType.FIELD 字段、枚举的常量
ElementType.METHOD 方法
ElementType.PARAMETER 方法参数
ElementType.CONSTRUCTOR 构造函数
ElementType.LOCAL_VARIABLE 局部变量
ElementType.ANNOTATION_TYPE 注解
ElementType.PACKAGE

@Relation 详细介绍

描述
RetentionPolicy.SOURCE 注解将被编译器丢弃,此处是源码阶段也就是 javac 编译时
RetentionPolicy.CLASS 注解在 class 中可用,但会被 vm 丢弃
RetentionPolicy.RUNTIME vm 运行期间也会保留注解,可以使用反射机制读取注解的信息

@Documented 介绍

将此注解包含在 javadoc 中

@Inherited 介绍

允许子类继承父类中的注解,千万不要误解是注解的嵌套,是 Class 类继承的时候,是否拥有父类的注解

3. 注解可用的类型

  • 所有基本类型(int、float、double,boolean)

  • String

  • Class

  • enum

  • Annotaion

  • 以上类型的数组

    注解可以嵌套注解

4. 默认值限制

元素必须具有默认值,默认值不能是 null

注解不支持继承,不像类一样可以通过 extends 继承

5. 创建一个简单的自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface CustomAnnotation {
}

二、读取注解上的信息

通过反射机制去获取注解上的信息

  • 创建各种类型的注解

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface AnnotationForClass {
        String value();
    }
    

    @Target(ElementType.CONSTRUCTOR)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface AnnotationForConstructor {
    String value();
    }

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface AnnotationForField {
    String value();
    }

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface AnnotationForMethod {
    String value();
    }

    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface AnnotationForParam {
    String value();
    }

  • 带有各种注解的测试类

    @AnnotationForClass(value = "AnnotationForClassValue")
    public class Test {
        @AnnotationForField(value = "AnnotationForFieldValue")
        private String name;
    
    <span class="hljs-meta">@AnnotationForMethod</span>(value = <span class="hljs-string">"AnnotationForMethodValue"</span>)
    <span class="hljs-keyword">public</span> <span class="hljs-title class_">String</span> <span class="hljs-title function_">getName</span>(<span class="hljs-params"></span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">name</span>;
    }
    
    <span class="hljs-keyword">public</span> <span class="hljs-built_in">void</span> <span class="hljs-title function_">setName</span>(<span class="hljs-params"><span class="hljs-meta">@AnnotationForParam</span>(value = <span class="hljs-string">"AnnotationForParamValue"</span>) <span class="hljs-built_in">String</span> name</span>) {
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">name</span> = name;
    }
    
    <span class="hljs-meta">@AnnotationForConstructor</span>(value = <span class="hljs-string">"AnnotationForConstructorValue"</span>)
    <span class="hljs-keyword">public</span> <span class="hljs-title class_">Test</span>() {
    }
    

    }

  • 获取注解以及注解上的信息

    public class Main {
    
    <span class="hljs-comment">// getDeclaredAnnotations 获取所有的注解</span>
    <span class="hljs-comment">// getDeclaredAnnotation 获取指定的注解</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> NoSuchMethodException, NoSuchFieldException {
        Class&lt;Test&gt; testClazz = Test.class;
    
        <span class="hljs-comment">// 获取(类、接口、枚举、注解)上注解的</span>
        <span class="hljs-type">AnnotationForClass</span> <span class="hljs-variable">annotationForClass</span> <span class="hljs-operator">=</span> testClazz.getDeclaredAnnotation(AnnotationForClass.class);
        System.out.println(<span class="hljs-string">"类上的注解的值\t"</span> + annotationForClass.value());
    
        <span class="hljs-comment">// 获取类中构造器的注解</span>
        Constructor&lt;Test&gt; constructor = testClazz.getConstructor();
        <span class="hljs-type">AnnotationForConstructor</span> <span class="hljs-variable">annotationForConstructor</span> <span class="hljs-operator">=</span> constructor.getDeclaredAnnotation(AnnotationForConstructor.class);
        System.out.println(<span class="hljs-string">"类中构造器的注解的值\t"</span> + annotationForConstructor.value());
    
        <span class="hljs-comment">// 获取类中字段的注解</span>
        <span class="hljs-type">Field</span> <span class="hljs-variable">nameField</span> <span class="hljs-operator">=</span> testClazz.getDeclaredField(<span class="hljs-string">"name"</span>);
        <span class="hljs-type">AnnotationForField</span> <span class="hljs-variable">annotationForField</span> <span class="hljs-operator">=</span> nameField.getDeclaredAnnotation(AnnotationForField.class);
        System.out.println(<span class="hljs-string">"类中字段的注解的值\t"</span> + annotationForField.value());
    
        <span class="hljs-comment">// 获取类中方法的注解</span>
        <span class="hljs-type">Method</span> <span class="hljs-variable">getNameMethod</span> <span class="hljs-operator">=</span> testClazz.getDeclaredMethod(<span class="hljs-string">"getName"</span>);
        <span class="hljs-type">AnnotationForMethod</span> <span class="hljs-variable">annotationForMethod</span> <span class="hljs-operator">=</span> getNameMethod.getDeclaredAnnotation(AnnotationForMethod.class);
        System.out.println(<span class="hljs-string">"类中方法的注解的值\t"</span> + annotationForMethod.value());
    
        <span class="hljs-comment">// 获取方法上参数的注解</span>
        <span class="hljs-type">Method</span> <span class="hljs-variable">setNameMethod</span> <span class="hljs-operator">=</span> testClazz.getDeclaredMethod(<span class="hljs-string">"setName"</span>, String.class);
        <span class="hljs-type">AnnotationForParam</span> <span class="hljs-variable">annotationForParam</span> <span class="hljs-operator">=</span> setNameMethod.getDeclaredAnnotation(AnnotationForParam.class);
        System.out.println(<span class="hljs-string">"类中方法的参数的注解的值\t"</span> + annotationForParam.value());
    }
    

    }

  • 运行结果

    类上的注解的值 AnnotationForClassValue
    类中构造器的注解的值 AnnotationForConstructorValue
    类中字段的注解的值 AnnotationForFieldValue
    类中方法的注解的值 AnnotationForMethodValue
    类中方法的参数的注解的值 AnnotationForParamValue