Halo
发布于 2022-05-12 / 131 阅读 / 0 评论 / 0 点赞

java注解

简介

是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明.
从JVM的角度看,注解本身对代码逻辑没有任何影响,如何使用注解完全由工具决定.
Java的注解可以分为三类: 编译器使用的注解, 工具处理.class文件使用的注解, 程序运行期能够读取的注解

底层

java Annotation 的组成中,有 3 个非常重要的主干类

interface Annotation

package java.lang.annotation;
public interface Annotation {

    boolean equals(Object obj);

    int hashCode();

    String toString();

    Class<? extends Annotation> annotationType();
}

enum ElementType

package java.lang.annotation;

public enum ElementType {
    TYPE,               /* 类、接口(包括注释类型)或枚举声明  */

    FIELD,              /* 字段声明(包括枚举常量)  */

    METHOD,             /* 方法声明  */

    PARAMETER,          /* 参数声明  */

    CONSTRUCTOR,        /* 构造方法声明  */

    LOCAL_VARIABLE,     /* 局部变量声明  */

    ANNOTATION_TYPE,    /* 注释类型声明  */

    PACKAGE             /* 包声明  */
}

enum RetentionPolicy

package java.lang.annotation;
public enum RetentionPolicy {
SOURCE, /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了 */

CLASS,             /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */

RUNTIME            /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */

}

编译器使用的注解

这类注解不会被编译进入.class文件,它们在编译后就被编译器扔掉了。

  • @Override:让编译器检查该方法是否正确地实现了覆写;
  • @SuppressWarnings:告诉编译器忽略此处代码产生的警告。

工具处理.class文件使用的注解

有些工具会在加载class的时候,对class做动态修改,实现一些特殊的功能。
这类注解会被编译进入.class文件,但加载结束后并不会存在于内存中。
这类注解只被一些底层库使用,一般我们不必自己处理。

程序运行期能够读取的注解

它们在加载后一直存在于JVM中,这也是最常用的注解.

注解的使用

定义一个注解时,可以定义配置参数, 但是参数必须是常量.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
/**
 * 检查类中字段是否符合规则
 */ 
public @interface Check {
    int maxLen() default 20; // 字段最大长度,默认20个字符
}
/**
 * 用户信息类
 */ 
public class User {

    @Check(maxLen=10)
    /** 用户名,最大长度10个字符 */
    String name = "";

}
/**
 * 测试类
 */ 
public class Test {
    public static void main(String[] args) {
        User user = new User();
        user.name = "123123";
        checkField(user);
        user.name = "123123123123";
        checkField(user); 
    }

    public static boolean checkField(Object obj) {
        Field[] fields = obj.getClass().getFields();
        for(Field field : fields) {
            Check check = field.getAnnotation(Check.class); 
            if(field.get(obj).toString().length() > check.maxLen()) {
                throw new Exception(field.getName() + "字段长度太长");
            } else {
                System.out.println(field.getName() + "字段长度通过验证"); 
            }
        }
    }
}

评论