Java — 注解

Java 注解(Annotation)又称为 Java 标注,是 Java5 开始支持加入源代码的特殊语法元数据。

Java 语言中的类、方法、变量、参数和包等都可以被标注。

Java 标注可以通过反射获取标注的内容,在编译器生成 class 文件时,标注可以被嵌入到字节码中。

Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容。

2.1、内置注解

Java 定义了一套注解,共有 10 个。5 个在 java.lang 包中,5 个在 java.lang.annotation 包中。

2.2、用在代码上的注解

注解 描述 @Override 检查该方法是否正确地重写了父类的方法。如果重写错误,会报编译错误。 @Deprecated 标记废弃的方法。如果使用该方法,会报编译警告。 @SuppressWarnings 提示编译器忽略注解中声明的警告。 @SafeVarargs Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。 @FunctionalInterface Java 8 开始支持,标识一个匿名函数或函数式接口。

2.3、用在其它注解上的注解

此类注解也称为 元注解(meta annotation)。

注解 描述 @Retention 标记在什么时候保存该注解信息,用于描述注解的生命周期。 @Target 标记该注解的使用范围。 @Documented 标记这些注解是否包含在用户文档中。 @Inherited 标记子类可以继承父类的注解。 @Repeatable Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

格式: public @interface 注解名称 {}

步骤:创建注解、定义注解的参数和默认值、用上元注解配置该注解。

3.1、创建注解

示例:定义一个可用于检查字符串长度的注解

public @interface Length {

}

3.2、定义参数和默认值

public @interface Length {
    // 最小长度
    int min() default 0;
    // 最大长度
    int max() default Integer.MAX_VALUE;
    // 长度不合法
    String message() default "长度不合法";
}

注意:

3.3、用元注解配置注解

Retention 译为保留,该注解定义了一个注解的生命周期。

参数 描述 RetentionPolicy.RUNTIME (运行期间有效)注解可以保留到程序运行的时候,它会被加载进入到JVM中,所以在程序运行时可以获取到它们 RetentionPolicy.CLASS (编译期间有效)注解只被保留到编译进行的时候,它并不会被加载到JVM中 RetentionPolicy.SOURCE (源码期间有效)注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视

// 运行期间有效
@Retention(RetentionPolicy.RUNTIME)
public @interface Length {
    int min() default 0;
    int max() default Integer.MAX_VALUE;
    String message() default "长度不合法";
}

Target 译为目标,该是最为常用的元注解,可以指定自己能够被应用于源码中的哪些位置。

参数 描述 ElementType.TYPE 给一个类型进行注解,比如类、接口、枚举 ElementType.FIELD 给属性进行注解 ElementType.METHOD 给方法进行注解 ElementType.PARAMETER 给一个方法内的参数进行注解 ElementType.CONSTRUCTOR 给构造方法进行注解 ElementType.LOCAL_VARIABLE 给局部变量进行注解 ElementType.ANNOTATION_TYPE 给一个注解进行注解 ElementType.PACKAGE 给一个包进行注解

// 只用用于类属性或局部变量上
@Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE})
public @interface Length {
    int min() default 0;
    int max() default Integer.MAX_VALUE;
    String message() default "长度不合法";
}

Documented 译为文档,标注了此注解的注解,能够将注解中的元素包含到 Javadoc 中去。

// 将该注解元素添加到JavaDoc中
@Documented
public @interface Length {
    int min() default 0;
    int max() default Integer.MAX_VALUE;
    String message() default "长度不合法";
}

Inherited 译为继承,使用该注解定义子类是否可继承父类定义的注解。

@Inherited 仅针对 @Target(ElementType.TYPE) 类型的注解有效,并且仅针对类的继承有效,对接口的继承无效。

// 使用该注解的类,其子类默认继承该注解(仅针对类的继承有效)
@Inherited
// 给一个类型进行注解,类、接口、枚举等
@Target(ElementType.TYPE)
public @interface Length {
    int min() default 0;
    int max() default Integer.MAX_VALUE;
    String message() default "长度不合法";
}

此时一个类用到了该注解

@Length(min = 2, max = 16, message = "昵称长度2~16之间")
public class Pet {}

其子类默认继承了该注解

// 相当于继承了@Length
public class Cat extends Pet {}

Repeatable 译为可重复,使用该元注解可以定义注解是否可重复。

// 作用于类的属性上
@Target(ElementType.FIELD)
// 注解Role注解,在类的属性上可使用多个Role注解
@Repeatable(Roles.class)
public @interface Role {
    String value() default "";
}
// 作用于类的属性上
@Target(ElementType.FIELD)
public @interface Roles {
    Role[] value();
}

@Repeatable 元注解标注了 @Role,而 @Repeatable 后面括号中的类相当于一个容器注解。

按照规定,它里面必须要有一个 value 的属性,属性类型是一个被 @Repeatable 注解标注过的注解数组。

经过 @Repeatable 修饰后,在某个类型声明处,就可以添加多个 @Role注解:

4.1、示例1

需求:使用 @length 注解判断学生姓名长度是否合法。

示例:

// 运行期间有效
@Retention(RetentionPolicy.RUNTIME)
// 作用于类的属性上
@Target({ElementType.FIELD})
public @interface Length {
    // 最小长度
    int min() default 0;
    // 最大长度
    int max() default Integer.MAX_VALUE;
    // 提示信息
    String message() default "长度不合法";
}
public class Student {

    @Length(min = 1, max = 3, message = "名称超长")
    private String name;

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public static void main(String[] args) throws NoSuchFieldException {
        Student student = new Student("上官飞燕");
        // 判断name属性上length注解是否存在
        boolean lengthPresent = student.getClass().getDeclaredField("name").isAnnotationPresent(Length.class);
        if (lengthPresent) {
            // 获取注解内容
            Length length = student.getClass().getDeclaredField("name").getAnnotation(Length.class);
            // 使用注解信息校验名称是否合法
            if (length.min()

运行:

名称超长,合法长度:1~3。当前长度:4

4.2、示例2

需求:使用 @Repeatable 注解获取学生所有的职位。

示例:

// 运行期间有效
@Retention(RetentionPolicy.RUNTIME)
// 作用于类的属性上
@Target(ElementType.FIELD)
public @interface Roles {
    Role[] value();
}
// 运行期有效
@Retention(RetentionPolicy.RUNTIME)
// 作用与类的属性上
@Target({ElementType.FIELD})
// 注解Role注解,在类的属性上可使用多Role注解
@Repeatable(Roles.class)
public @interface Role {
    String value() default "";
}
public class Student {

    @Role("学习委员")
    @Role("体育委员")
    private String name;

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public static void main(String[] args) throws NoSuchFieldException {
        Student student = new Student("王五");
        // 判断name属性上@Role注解是否存在
        Role[] roles = student.getClass().getDeclaredField("name").getAnnotationsByType(Role.class);
        if (roles.length == 0) {
            System.out.println("Student.name属性上没有找到@Role注解");
        } else {
            // 获取注解内容
            for (Role role : roles) {
                System.out.println(student.getName() + " = " + role.value());
            }
        }
    }
}

运行:

王五 = 学习委员
王五 = 体育委员

Original: https://www.cnblogs.com/bybeiya/p/15086690.html
Author: 北涯
Title: Java — 注解

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585919/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 什么是虚拟计算机集群

    这个问题来自近期几位网友的私信,他们不约而同问到一个问题:什么是虚拟计算机集群?Laxcus分布式操作系统是如何做的?下面就正式回答一下这个问题。 在我们传统的认知里,或者大家平常…

    Linux 2023年6月6日
    0156
  • Xshell配置ssh免密码登录-密钥公钥(Public key)与私钥(Private Key)登录【已成功实例】

    本文转自https://blog.csdn.net/qjc_501165091/article/details/51278696 ssh登录提供两种认证方式:口令(密码)认证方式和…

    Linux 2023年5月28日
    0120
  • 函数的设计和使用

    1.函数的定义 将可能需要反复执行的代码封装为函数,并在需要该功能的地方进行调用,不仅可以实现代码复用,更重要的是可以保证代码的一致性,只需要修改函数代码则所有调用均受影响。 设计…

    Linux 2023年6月7日
    0241
  • PHP使用pdfparser实现对PDF转换成本文

    使用pdfparser对PDF转换成文本形式,转换后没有格式。 原始PDF: 转换成文本: 第一步:安装pdfparser composer require smalot/pdfp…

    Linux 2023年6月7日
    0142
  • 用户身份标识与账号体系实践

    互联网的账号自带备忘机制; 一、业务背景 通常在系统研发的过程中,需要不断适配各种业务场景,扩展服务的领域和能力,一般会将构建的产品矩阵划分出多条业务线,以便更好的管理; 由于各个…

    Linux 2023年6月14日
    0125
  • 误操作使用fdisk删除了/root所在分区,该如何把文件拷贝出来

    误操作 fdisk命令误操作,将 /root 所在分区删除后新建了…… 恢复尝试1 起初以为是改一下 /etf/fstab 就好了,于是进入急救模式,尝试 …

    Linux 2023年6月8日
    0167
  • pwm驱动

    1.1、参考博客 参考的教程如下: 1.2、什么是PWM 脉冲宽度调制(PWM),是英文”Pulse Width Modulation”的缩写,简称脉宽调制…

    Linux 2023年6月13日
    0145
  • JVM学习 类加载子系统

    JVM 哔哩哔哩 尚硅谷视频 宋红康老师 Java代码执行流程 简图 详细图 1、类加载子系统 类加载器子系统的作用 类加载器子系统负责从文件系统或者网络中加载Class文件,cl…

    Linux 2023年6月7日
    0146
  • Redis从入门到精通:中级篇

    原文链接:http://www.cnblogs.com/xrq730/p/8944539.html,转载请注明出处,谢谢 本文目录 上一篇文章以认识Redis为主,写了Redis系…

    Linux 2023年5月28日
    0136
  • OSPF之Default-router-advertise 解析

    1、关于default-route-advertise命令 Ospf是可以通过import-route命令引入外部路由的,但很少有人会注意到,在默认情况下,ospf是不会引入来自外…

    Linux 2023年6月14日
    0140
  • 【Leetcode】768. 最多能完成排序的块 II

    arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个”块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。 …

    Linux 2023年6月6日
    0140
  • Docker Manager for Docker Swarm deploy

    一、Swarm概述 Swarm是Docker公司在2014年12月初发布的一套较为简单的工具,用来管理Docker集群,它将一群Docker宿主机变成一个单一的,虚拟的主机。Swa…

    Linux 2023年6月14日
    0148
  • zabbix快速安装(yum)

    1、先卸载系统自带数据库 [root@bogon ~]# rpm -e mariadb-libs-5.5.56-2.el7.x86_64 –nodeps 2、安装mys…

    Linux 2023年6月6日
    0116
  • 1:文件与目录

    CD 切换当前工作目录 mkdir 创建目录 re -dir 删除目录 pwd 打印当前工作目录 绝对路径和相对路径 硬链接 和软链接 CP拷贝 MV 移动 dirname 和 b…

    Linux 2023年6月7日
    0170
  • redis

    PHP-redis:http://pecl.php.net/package/redis PHP-redis中文文档(redis各种方法介绍):http://www.cnblogs….

    Linux 2023年5月28日
    0122
  • Docker安装使用–Centos

    前言 Docker安装使用 安装步骤 卸载旧版本 安装utils 配置utils的存储库 安装Docker 安装指定版本Docker 验证安装 官网安装说明 阿里云镜像加速 Doc…

    Linux 2023年6月7日
    0129
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球