Java中的注解技术讲解

Java中的注解(Annotation)是一种在代码中嵌入元数据的机制,不直接参与业务逻辑,而是为编译器、开发工具以及运行时提供额外的信息和指导。下面我们将由浅入深地讲解Java注解的概念、实现原理、各种应用场景,并通过代码示例帮助理解。


1. 注解的基本概念

注解类似于“标签”,可以附加在类、方法、属性、参数、局部变量等位置,用于说明该代码元素的特殊意义或行为。注解本身不会影响程序的运行,但可以被编译器、工具或通过反射读取并执行相应的处理逻辑。

  • 作用:
    • 提供元数据: 指示编译器进行检查(如@Override标识的方法必须是重写父类方法)。
    • 代码生成与校验: 一些工具可以根据注解生成额外代码或者配置文件。
    • 运行时行为控制: 框架通过读取注解信息动态实现依赖注入、事务管理等功能(例如Spring、JUnit等)。

2. 常见内置注解与使用场景

Java提供了一些内置注解,开发者无需额外定义,可直接使用:

  1. @Override

    • 用于标注一个方法是重写父类或接口中的方法。
    • 示例:
      public class Parent {public void display() {System.out.println("Parent display");}
      }public class Child extends Parent {@Overridepublic void display() {System.out.println("Child display");}
      }
      
    • 作用: 避免因方法签名错误而导致没有成功重写父类方法。
  2. @Deprecated

    • 表示一个方法、类或字段已过时,不建议继续使用。
    • 示例:
      public class Example {@Deprecatedpublic void oldMethod() {System.out.println("This method is deprecated");}
      }
      
    • 作用: 编译时会给出警告,鼓励开发者采用新的实现方式。
  3. @SuppressWarnings

    • 用于抑制编译器特定的警告信息。
    • 示例:
      @SuppressWarnings("unchecked")
      public void useLegacyCode() {List list = new ArrayList();// 这里可能涉及未检查的类型转换
      }
      

3. 自定义注解

Java允许开发者定义自己的注解,可以通过元注解(Meta-Annotation)来指定注解的行为。

3.1 定义自定义注解

自定义注解通常使用@interface关键字定义,并结合以下元注解设置行为:

  • @Retention:指定注解的生命周期(SOURCE、CLASS或RUNTIME)。
    • RUNTIME的注解能在运行时通过反射读取。
  • @Target:定义注解可以应用到哪些元素(例如METHOD、FIELD、TYPE等)。
  • @Inherited:允许子类继承父类的注解(只对类有效)。
  • @Documented:将注解包含在Javadoc中。

示例:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;// 该注解在运行时可见,并且只能应用于方法和类
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnotation {// 定义一个具有默认值的属性String value() default "default value";// 定义一个无默认值的属性,使用时必须赋值int number();
}

3.2 使用自定义注解

使用自定义注解时,就像使用内置注解一样,直接在代码元素上加上即可。

示例:

@MyAnnotation(number = 10, value = "ExampleClass")
public class ExampleClass {@MyAnnotation(number = 5, value = "ExampleMethod")public void exampleMethod() {System.out.println("Executing example method");}public static void main(String[] args) {ExampleClass obj = new ExampleClass();obj.exampleMethod();}
}

3.3 通过反射读取注解

注解最强大的功能之一便是能在运行时通过反射读取它们的信息,从而根据注解进行对应的处理。

示例:

import java.lang.reflect.Method;public class AnnotationProcessor {public static void main(String[] args) {try {// 获取类的字节码Class<?> clazz = Class.forName("ExampleClass");// 检查类上是否有MyAnnotationif (clazz.isAnnotationPresent(MyAnnotation.class)) {MyAnnotation classAnnotation = clazz.getAnnotation(MyAnnotation.class);System.out.println("Class Annotation: value = " + classAnnotation.value()+ ", number = " + classAnnotation.number());}// 遍历所有方法for (Method method : clazz.getDeclaredMethods()) {if (method.isAnnotationPresent(MyAnnotation.class)) {MyAnnotation methodAnnotation = method.getAnnotation(MyAnnotation.class);System.out.println("Method " + method.getName() + " Annotation: value = " + methodAnnotation.value() + ", number = " + methodAnnotation.number());}}} catch (ClassNotFoundException e) {e.printStackTrace();}}
}

此例演示了如何检查类和方法上是否存在MyAnnotation注解,并输出相应的属性值。


4. 元注解(Meta-Annotations)的深入理解

元注解用于修饰其他注解,本质上是为注解定义行为的工具。主要元注解包括:

  1. @Retention

    • 作用: 定义注解的保留策略
    • 策略:
      • RetentionPolicy.SOURCE:注解仅在源码中存在,编译器会忽略,不会写入.class文件。
      • RetentionPolicy.CLASS:注解会被编译到class文件,但运行时不保留(默认策略)。
      • RetentionPolicy.RUNTIME:注解不仅被编译到class文件,而且在运行时通过反射可获取。
  2. @Target

    • 作用: 限定注解能够应用的元素类型,如类、方法、字段、参数等。
    • 示例:
      @Target(ElementType.METHOD)
      public @interface MethodAnnotation { }
      
  3. @Inherited

    • 作用: 允许子类继承父类的注解(仅适用于类)。
    • 示例:
      @Inherited
      @Retention(RetentionPolicy.RUNTIME)
      public @interface InheritableAnnotation { }@InheritableAnnotation
      public class Parent { }public class Child extends Parent { }
      // Child类同样具备InheritableAnnotation注解信息
      
  4. @Documented

    • 作用: 表明使用该注解的信息应被包含在Javadoc中。

5. 注解的高级使用场景

5.1 框架配置与依赖注入

许多现代框架利用注解简化配置。例如,Spring使用注解来标识组件、注入依赖和配置事务:

  • 示例:
    @Service
    public class UserService {@Autowiredprivate UserRepository userRepository;
    }
    
    这里@Service@Autowired注解告诉Spring这是一个服务类并需要自动注入相应的依赖。

5.2 单元测试(JUnit)

JUnit使用注解标识测试方法,使得测试代码不依赖外部配置:

  • 示例:
    import org.junit.Test;
    import static org.junit.Assert.assertEquals;public class CalculatorTest {@Testpublic void testAdd() {Calculator calc = new Calculator();int result = calc.add(5, 3);assertEquals(8, result);}
    }
    
    @Test注解标注了测试方法,JUnit框架可以自动识别和执行这些测试方法。

5.3 日志记录与AOP(面向切面编程)

通过自定义注解与AOP相结合,可以在方法执行前后自动记录日志或执行其他横切逻辑。

  • 示例:定义日志注解
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Log {String value() default "";
    }
    
  • 示例:使用AOP切面读取注解信息
    @Aspect
    @Component
    public class LogAspect {@Around("@annotation(logAnnotation)")public Object logExecution(ProceedingJoinPoint joinPoint, Log logAnnotation) throws Throwable {System.out.println("Start executing: " + joinPoint.getSignature().getName() + " with log: " + logAnnotation.value());Object result = joinPoint.proceed();System.out.println("Finished executing: " + joinPoint.getSignature().getName());return result;}
    }
    
    在这里,任何标注了@Log注解的方法都会在执行前后打印日志信息。

5.4 编译时检查和代码生成

注解处理器(Annotation Processor)允许在编译期间对源代码进行扫描和处理,从而自动生成代码、配置文件或检查不符合规范的地方。常见的例子如:Lombok 就是通过注解处理器来生成setter/getter方法,减少样板代码。

  • 示例:自定义注解处理器基本流程
    开发者可以实现javax.annotation.processing.AbstractProcessor,并通过@SupportedAnnotationTypes声明支持的注解:
    @SupportedAnnotationTypes("com.example.MyAnnotation")
    @SupportedSourceVersion(SourceVersion.RELEASE_8)
    public class MyAnnotationProcessor extends AbstractProcessor {@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {// 执行自定义处理逻辑,如代码生成或检查代码结构}return true;}
    }
    
    使用注解处理器的好处是可以在编译期暴露问题,而不必等到运行时才发生异常。

6. 总结

  • 入门: 注解本质上是为代码添加元数据,能为编译器、工具或框架提供指导信息,常见的如@Override@Deprecated@SuppressWarnings
  • 自定义注解: 利用@interface关键字和元注解(如@Retention@Target)可以定义适用于特定场景的自定义注解,并结合反射技术实现动态处理。
  • 高级应用: 在框架配置、依赖注入、单元测试、AOP日志记录以及编译时代码生成等场景中,注解均发挥着非常重要的作用,极大地提高了代码的可维护性和扩展性。

通过上述讲解和示例代码,能更全面、深入地理解Java中注解的概念和应用场景。这种机制不仅在Java EE和Spring等框架中被广泛应用,而且也成为现代Java开发中不可或缺的工具之一。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

京东与喜茶关系破裂:切断所有合作 禁止进入办公场所

快科技4月10日消息&#xff0c;据报道&#xff0c;京东集团近日被曝出内部下发全员禁令&#xff0c;全面封杀喜茶产品进入办公区域。 据知情人士透露&#xff0c;京东人力行政部门发布的通知明确规定&#xff1a;全国各职场禁止与喜茶品牌开展任何形式的合作&#xff1b;员工不…

+++++背到厌倦。持续更新

Spring IoC 的工作流程: 读取 BeanDefinition: Spring 容器启动时&#xff0c;会读取 Bean 的配置信息 (例如 XML 配置文件、注解或 Java 代码)&#xff0c;并将这些配置信息转换为 BeanDefinition 对象。创建 Bean 实例: 根据 BeanDefinition 中的信息&#xff0c;Spring 容器…

如何在Git历史中抹掉中文信息并翻译成英文

如何在Git历史中抹掉中文信息并翻译成英文 在软件开发和版本控制领域&#xff0c;维护一个清晰、一致的代码历史记录是至关重要的。然而&#xff0c;有时我们可能会遇到需要修改历史提交的情况&#xff0c;比如删除敏感信息或修正错误。本文将详细探讨如何在Git历史中抹掉中文…

21 天 Python 计划:MySQL中DML与权限管理

文章目录 前言一、介绍二、MySQL数据操作&#xff1a;DML2.1 插入数据&#xff08;INSERT&#xff09;2.1.1 插入完整数据&#xff08;顺序插入&#xff09;2.1.2 指定字段插入数据2.1.3 插入多条记录2.1.4 插入查询结果 2.2 更新数据&#xff08;UPDATE&#xff09;2.3 删除数…

微信小程序 -- 原生封装table

文章目录 table.wxmltable.wxss注意 table.js注意 结果数据结构 最近菜鸟做微信小程序的一个查询功能&#xff0c;需要展示excel里面的数据&#xff0c;但是菜鸟找了一圈&#xff0c;也没发现什么组件库有table&#xff0c;毕竟手机端好像确实不太适合做table&#xff01; 菜鸟…

LangChain-输出解析器 (Output Parsers)

输出解析器是LangChain的重要组件&#xff0c;用于将语言模型的原始文本输出转换为结构化数据。本文档详细介绍了输出解析器的类型、功能和最佳实践。 概述 语言模型通常输出自然语言文本&#xff0c;但在应用开发中&#xff0c;我们经常需要将这些文本转换为结构化的数据格式…

【安全】加密算法原理与实战

为了理解SSL/TLS原理&#xff0c;大家需要掌握一些加密算法的基础知识。当然&#xff0c;这不是为了让大家成为密码学专家&#xff0c;所以只需对基础的加密算法有一些了解即可。基础的加密算法主要有哈希&#xff08;Hash&#xff0c;或称为散列&#xff09;​、对称加密(Symm…

MySQL 优化教程:让你的数据库飞起来

文章目录 前言一、数据库设计优化1. 合理设计表结构2. 范式化与反范式化3. 合理使用索引 二、查询优化1. 避免使用 SELECT *2. 优化 WHERE 子句3. 优化 JOIN 操作 三、服务器配置优化1. 调整内存分配2. 调整并发参数3. 优化磁盘 I/O 四、监控与分析1. 使用 EXPLAIN 分析查询语句…

LangChain4j(1):初步认识Java 集成 LLM 的技术架构

LangChain 作为构建具备 LLM 能力应用的框架&#xff0c;虽在 Python 领域大放异彩&#xff0c;但 Java 开发者却只能望洋兴叹。LangChain4j 正是为解决这一困境而诞生&#xff0c;它旨在借助 LLM 的强大效能&#xff0c;增强 Java 应用&#xff0c;简化 LLM 功能在Java应用中的…

Linux服务器安装百度飞桨3.0(pip docker)

Linux安装部署百度飞桨3.0 1.官方文档指引2.确认服务器型号2.1 确认Python版本2.2 确认pip是否安装2.3 确认计算平台 3.本机安装&#xff08;基于通过 pip 安装&#xff09;3.1 下载安装 PaddlePaddle3.2 安装PaddleX3.2.1 安装PaddleX3.2.2 命令行规范3.2.3 运行示例3.2.4 查看…

Spring Boot 自动加载流程详解

前言 Spring Boot 是一个基于约定优于配置理念的框架&#xff0c;它通过自动加载机制大大简化了开发者的配置工作。本文将深入探讨 Spring Boot 的自动加载流程&#xff0c;并结合源码和 Mermaid 图表进行详细解析。 一、Spring Boot 自动加载的核心机制 Spring Boot 的自动加…

2025年危化品安全管理人员备考指南|智能题库+核心考点解析

作为危化品生产单位安全管理人员&#xff08;主要负责人&#xff09;&#xff0c;考试内容主要涵盖三大模块&#xff1a; 法律法规体系 《安全生产法》修订要点&#xff08;2023版&#xff09; 危险化学品重大危险源辨识标准&#xff08;GB 18218&#xff09; 最新《化工过…

如何优雅使用 ReentrantLock 进行加解锁:避免常见坑点,提高代码可维护性

引言&#xff1a;锁的基本概念和问题 在多线程编程中&#xff0c;为了确保多个线程在访问共享资源时不会发生冲突&#xff0c;我们通常需要使用 锁 来同步对资源的访问。Java 提供了不同的锁机制&#xff0c;其中 ReentrantLock 是一种最常用且功能强大的锁&#xff0c;它属于…

Redhat红帽 RHCE8.0认证体系课程

课程大小&#xff1a;7.7G 课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/90546064 更多资源下载&#xff1a;关注我 红帽企业 Linux 系统的管理技能已经成为现代数据中心的核心竞争力。 Linux 在支持混合云、跨物理服务器、虚机、私有云和公共云计…

Shell脚本编程

目录 1. Shell脚本概述 什么是Shell&#xff1f; Shell的作用 常见的Shell类型 2. 环境搭建与安装 Linux系统 macOS系统 Windows系统 3.安装并配置Zsh&#xff08;macOS/Linux&#xff09; 4. Shell基础语法 变量与数据类型 输入交互 5. Shell脚本进阶 进程管理 …

学生管理系统(Python)

运行结果&#xff1a; 源代码&#xff1a; """ 项目&#xff1a;类似于学生管理系统---增删改查 """ #封装一个学生类 import random class Student: def __init__(self,stuid,name,score): self.stuid stuid self.name name self.score …

电商素材革命:影刀RPA魔法指令3.0驱动批量去水印,实现秒级素材净化

本文 去除水印实操视频展示电商图片水印处理的困境​影刀 RPA 魔法指令 3.0 强势登场​利用魔法指令3.0两步实现去除水印操作关于影刀RPA 去除水印实操视频展示 我们这里选择了4张小红书里面比较帅气的图片&#xff0c;但凡用过小红书的都知道&#xff0c;小红书右下角是会有小…

Seq2Seq - GRU补充讲解

nn.GRU 是 PyTorch 中实现门控循环单元&#xff08;Gated Recurrent Unit, GRU&#xff09;的模块。GRU 是一种循环神经网络&#xff08;RNN&#xff09;的变体&#xff0c;用于处理序列数据&#xff0c;能够更好地捕捉长距离依赖关系。 ⭐重点掌握输入输出部分输入张量&#…

设计模式-观察者模式和发布订阅模式区别

文章目录 其他不错的文章 二者有类似的地方&#xff0c;也有区别。 引用的文章说的已经比较清楚了&#xff0c;这里只列出对比图。 对比点观察者模式发布订阅模式中间人角色无事件中心&#xff0c;观察者直接订阅目标有事件中心&#xff0c;发布者与订阅者通过事件中心通信关系…

【SQL】基于多源SQL 去重方法对比 -- 精华版

【SQL】基于SQL 去重方法对比 -- 精华版 一、引言二、基于SQL去重方法完整对比1. MySQL去重方法及优劣势1.1 ​DISTINCT关键字1.2 GROUP BY子句1.3 UNION系列操作1.4 子查询 自关联 2. Hive去重方法及优劣势2.1 DISTINCT关键字2.2 ​GROUP BY子句2.3 ​ROW_NUMBER窗口函数2.4 …