Java—注解机制详解

概念

注解是类的组成部分,可以为类携带额外的信息,提供一种安全的注释标记机制,用于将任何信息或元数据与程序元素(如类、方法、成员变量等)关联。

  • 注解是供编译器或JVM使用的,编译器或JVM可以根据注解执行相应的功能。
  • 注解类似于修饰符,适用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。
  • 父类中的注解不能被子类继承。

注解的作用

  • 标记:为类、方法或变量添加元数据,便于工具或框架识别。
  • 框架支持:许多框架利用注解和反射来实现功能,这是框架的底层基础技术。
  • 编译时检查:如 @Override 用于方法重写约束,@FunctionalInterface 用于函数式接口约束。

注解格式

定义格式:自定义注解用 @interface 关键字,注解默认可以标记很多地方

修饰符 @interface 注解名{// 注解属性
}

使用注解的格式:@注解名

// 自定义注解
@interface MyAnnotation {String value();
}// 使用注解
@MyAnnotation(value = "示例注解")
public class Example {@Overridepublic String toString() {return "这是一个示例类";}
}

常用注解

@Override:检查方法是否正确重写父类方法。
@Deprecated:标记某个方法或类为过时,不建议使用。
@SuppressWarnings:抑制特定的编译器警告。
@FunctionalInterface:指示接口为函数式接口。

注解属性

普通属性

注解可以包含属性,属性名必须带 ()。在使用注解时,属性必须赋值,除非属性定义了默认值。

属性的格式:

  • 格式 1:数据类型 属性名()
  • 格式 2:数据类型 属性名() default 默认值

适用的数据类型:

  • 八种基本数据类型:int、short、long、double、byte、char、boolean、float
  • String
  • Class
  • 以上类型的数组形式也被支持

特殊属性

注解中有一个特殊属性名称:value

  • 如果注解只有一个 value 属性,可以在使用时省略 value 名称。
  • 如果有多个属性且没有默认值,则 value 属性不能省略。

示例

// 自定义注解
@interface MyAnnotation {String name(); // 必须提供int age() default 18; // 默认值为18String[] tags() default {}; // 默认值为空数组String value(); // 特殊属性
}// 使用注解
@MyAnnotation(name = "示例", value = "测试")
public class Example {// ...
}// 省略 value 属性
@MyAnnotation(name = "示例", value = "测试")
public class AnotherExample {// ...
}

在以上示例中,MyAnnotation 定义了多个属性,包括一个特殊属性 value。使用时可以选择性地省略 value。

元注解概述

元注解是 Java 中用于注解自定义注解的注解,主要由 Sun 公司提供。它们可以控制自定义注解的应用范围和行为。元注解包括以下四种:

@Target

用于指定自定义注解可以应用于哪些 Java 元素。其默认值为任何元素。可用值定义在 ElementType 类中,主要包括:

  • ElementType.CONSTRUCTOR:用于描述构造器。
  • ElementType.FIELD:用于描述成员变量、对象、属性(包括 enum 实例)。
  • ElementType.LOCAL_VARIABLE:用于描述局部变量。
  • ElementType.METHOD:用于描述方法。
  • ElementType.PACKAGE:用于描述包。
  • ElementType.PARAMETER:用于描述方法参数。
  • ElementType.TYPE:用于描述类、接口(包括注解类型)或 enum 声明。

@Retention

定义注解的生命周期,声明注解的作用范围。可用值定义在 RetentionPolicy 枚举类中:

  • RetentionPolicy.SOURCE:在编译阶段丢弃,这些注解在编译结束后不再存在于字节码中,仅用于源码阶段,如 @Override 和 @SuppressWarnings。
  • RetentionPolicy.CLASS:在类加载时丢弃,字节码文件中存在,但在运行时不存在。这是默认值。
  • RetentionPolicy.RUNTIME:在运行期保留该注解,因此可以使用反射机制读取注解信息。自定义注解通常使用这种方式。

@Inherited

  • 表示修饰的自定义注解可以被子类继承。仅适用于类类型的注解。

@Documented

  • 指示该注解是否应包含在 Java 文档中。使用此注解标记的自定义注解在生成的文档中会包含其元信息。

示例

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyCustomAnnotation {String value() default "default";
}

注解解析概述

在 Java 开发中,注解解析是理解和利用注解的关键。通过反射机制,可以动态地获取类、方法、字段等元素上的注解信息。以下是与注解解析相关的核心接口和类的概述。

相关接口与类

  • Annotation:所有注解的父类,所有自定义注解都继承自这个接口。
  • AnnotatedElement:定义了与注解解析相关的方法,提供了一系列获取注解的功能。
  • Class、Method、Field、Constructor:这些类实现了 AnnotatedElement 接口,因此可以通过它们获取注解信息。

Class 类 API

  • Annotation[] getDeclaredAnnotations():获取当前对象上声明的所有注解,返回一个注解数组。
  • T getDeclaredAnnotation(Class<T> annotationClass):根据注解类型获取对应的注解对象,仅返回当前对象上声明的注解。
  • T getAnnotation(Class<T> annotationClass):获取当前对象及其父类上声明的指定类型的注解。
  • boolean isAnnotationPresent(Class<Annotation> annotationClass):判断当前对象是否使用了指定类型的注解。
  • boolean isAnnotation():判断当前 Class 对象是否表示注解类型。

注解的原理

注解本质上是特殊接口,继承了 Annotation 接口。在运行时,Java 为每个注解生成一个动态代理类。当通过反射获取注解时,返回的是动态代理对象(例如 $Proxy1),通过这个代理对象调用注解的方法时,实际上会回调 AnnotationInvocationHandler 的 invoke 方法。

这个方法从 memberValues 这个 Map 中获取注解属性的值,而 memberValues 的数据来源于 Java 常量池。

注解数据解析原理

注解的解析通常遵循以下步骤:

  1. 确定注解的作用对象(类、方法等)。
  2. 获取对应的 Class 对象。
  3. 使用上述 API 方法从 Class 对象中获取注解信息。

示例

package com.example;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {String value();
}@MyAnnotation(value = "Example Class")
class ExampleClass {
}public class AnnotationParser {public static void main(String[] args) {Class<ExampleClass> exampleClass = ExampleClass.class;// 检查是否存在注解if (exampleClass.isAnnotationPresent(MyAnnotation.class)) {// 获取注解MyAnnotation annotation = exampleClass.getAnnotation(MyAnnotation.class);System.out.println("注释值: " + annotation.value());}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/150152.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

云岚到家 第一天实战总结

为什么使用post发送请求&#xff0c;参数依旧会被拼接带url上呢&#xff1f;这应该就是param 与data传参的区别。即param传参数参数会被拼接到url后&#xff0c;data会以请求体传递 不一定post发送请求&#xff0c;数据一定在请求体中&#xff0c;主要是看数据的格式。 后端c…

c++924

2 #include <iostream> #include <cstring>using namespace std;class MyString { private:char *str; // 记录C风格的字符串int size; // 记录字符串的实际长度public:// 定义无参构造MyString() : size(0) {str new char[1];str[0] \0;cou…

《深度学习》—— 神经网络中的数据增强

文章目录 一、为什么要进行数据增强&#xff1f;二、常见的数据增强方法1. 几何变换2. 颜色变换3. 尺寸变换4. 填充5. 噪声添加6. 组合变换 三、代码实现四、注意事项五、总结 一、为什么要进行数据增强&#xff1f; 神经网络中的数据增强是一种通过增加训练数据的多样性和数量…

Python接口自动化测试输出日志到控制台和文件

一、日志的作用 一般程序日志出自下面几个方面的需求&#xff1a; 1. 记录用户操作的审计日志&#xff0c;甚至有的时候就是监管部门的要求。 2. 快速定位问题的根源 3. 追踪程序执行的过程。 4. 追踪数据的变化 5. 数据统计和性能分析 6. 采集运行环境数据 一般在程序上线之后…

2024 年 8 月公链行业研报:Layer 1、比特币 Layer 2 和以太坊 Layer 2 趋势分析

作者&#xff1a;Stella L (stellafootprint.network) 数据来源&#xff1a;Footprint Analytics 公链研究页面 8 月&#xff0c;加密货币市场波动剧烈&#xff0c;比特币和以太坊均遭遇了明显下跌。Layer 1 区块链普遍遭受市场颓势&#xff0c;然而&#xff0c;Tron 却逆势…

考研数据结构——C语言实现插入排序

插入排序是一种简单直观的比较排序算法&#xff0c;它的工作原理是通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已排序序列中从后向前扫描&#xff0c;找到相应位置并插入。插入排序在实现上&#xff0c;通常采用in-place&#xff08;原地排序&#xff09;&#…

【python篇】python pickle模块一篇就能明白,快速理解

持久性就是指保持对象&#xff0c;甚至在多次执行同一程序之间也保持对象。通过本文&#xff0c;您会对 Python对象的各种持久性机制&#xff08;从关系数据库到 Python 的 pickle以及其它机制&#xff09;有一个总体认识。另外&#xff0c;还会让您更深一步地了解Python 的对象…

【深度】边缘计算神器之数据网关

分布式计算、云边协同、互联互通是边缘计算设备的三项重要特征。 边缘计算设备通过分布式计算模式&#xff0c;将数据处理和分析任务从中心化的云平台下放到设备网关&#xff0c;即更接近数据源的地方&#xff0c;从而显著降低了数据传输的延迟&#xff0c;提高了响应速度和处…

算法4-----综合训练(3)

一&#xff1a;优美的排列 题目&#xff1a; 有1~n的n个整数&#xff0c;用这些数构造一个数组perm&#xff0c;只要构造的数组满足以下两个条件&#xff1a; &#xff08;1&#xff09;i可以被perm[i]整除 &#xff08;2&#xff09;perm[i]可以被i整除 返回其能构造出的…

影刀RPA应用迁移应用复制完整步骤-本地工具

影刀应用迁移工具本地版 不需要输入影刀的用户名和密码就能实现应用的迁移 依赖本地电脑中登录的账号 使用方法 打开软件需要激活,请联系: 左侧选择一个账号选择需要迁移的应用选择目标账号选择要替换的应用 需要用目标账号创建一个空应用,然后在这一步选择点击替换 Q&A…

3. 轴指令(omron 机器自动化控制器)——>MC_MoveRelative

机器自动化控制器——第三章 轴指令 5 MC_MoveRelative变量▶输入变量▶输出变量▶输入输出变量 功能说明▶指令详情▶时序图▶重启运动指令▶多重启动运动指令▶异常 MC_MoveRelative 指定自指令当前位置起的移动距离&#xff0c;进行定位。 指令名称FB/FUN图形表现ST表现MC…

【环境搭建】MySQL安装部署

Win64安装MySQL Windows的玩法比较少&#xff0c;没有像MAC一样给你提供mysqld-safe等等各种的启动脚本&#xff0c;只有手动启动或者是以服务启动Mysql。 点击下载&#xff1a;MySQL5.5-8.0.7z (密码是11) 1.下载软件 这一步下载好软件就可以了&#xff0c;下载地址&#xff…

海山数据库(He3DB)技术分享:He3DB Virtual File Descriptor实现原理

引言 在 He3DB 这样的数据库系统中&#xff0c;文件操作不仅频繁而且复杂。操作系统提供的文件描述符&#xff08;FD&#xff09;数量是有限的&#xff0c;尤其在高并发和大规模数据库操作中&#xff0c;文件描述符资源可能迅速耗尽。为了应对这一挑战&#xff0c;He3DB 引入了…

《深度学习》CNN 数据增强、保存最优模型 实例详解

目录 一、数据增强 1、什么是数据增强 2、目的 3、常用的数据增强方法 4、数据预处理 用法&#xff1a; 5、使用数据增强增加训练数据 二、保存最优模型 1、什么是保存最优模型 2、定义CNN模型 运行结果&#xff1a; 3、设置训练模式 4、设置测试模式、保存最优模…

指针变量的自增、自减运算

指针变量的自增、自减运算相比较于普通变量的自增、自减运算又什么区别呢&#xff1f; 让我们先来复习一下普通变量的自增、自减运算 int main() {int i; //定义一个整型变量printf("请输入一个数字&#xff1a;\n");scanf("%d&qu…

查座位号小程序

如何通过关键词查询信息&#xff1f; 在这个信息化的时代&#xff0c;查座位号小程序为我们提供了一种方便快捷的方式来查询座位信息。无论是在大型会议还是日常办公中&#xff0c;通过小程序快速查找座位号&#xff0c;可以大大提高工作效率。以下是详细的使用指南&#xff0c…

初始MYSQL数据库(7)—— 视图

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; MYSQL 引言 前面我们学习MySQL数据库时&#xff0c;创建表之后&#xff0c;会在表中插入数据&#xff0c;在需要的时候&#xff0c;也会进行…

stm32 gpio I/O模式以及iic访问

1&#xff0c;硬件补充连接原理图引脚 #define FLASH_BASE ((uint32_t)0x08000000) /*!< FLASH(up to 1 MB) base address in the alias region */ #define CCMDATARAM_BASE ((uint32_t)0x10000000) /*!< CCM(core coupled mem…

点亮一个LED灯

一、任务分析 一个灯怎么样才会亮&#xff1f; 图中的小灯两端接正负极&#xff0c;小灯就会点亮&#xff0c;但是我们不能主动控制灯的亮灭&#xff0c;于是加入了开关。开关打开断开小灯正极&#xff0c;小灯就会熄灭&#xff0c;反之则点亮。 在板子上的灯是如何连接的&…

【学习笔记】exkmp(Z函数)

本文参考洛谷题解&#xff1a;https://www.luogu.com.cn/article/cq4b4e5f 侵删 前言 exkmp 和 kmp 要求的东西比较类似。 exkmp 可以求出 a i . . . n a_{i...n} ai...n​ 和 b b b 的最长公共前缀。 这玩意也称 z 函数。 算法流程 求解 nxt 数组 定义 n x t i nxt_i …