Java Annotation学习笔记

简介: 作为一个早期短暂从事过C++开发工作的程序员,我个人认为Annotation可能是Java与C++语言较大的不同点之一,这也是一个前C++程序员由衷认为Java可能、或许、maybe要比C++更好用的原因之一。本文通过一个小例子展示了自定义注解的全过程。

作为一个早期短暂从事过C++开发工作的程序员,我个人认为Annotation可能是Java与C++语言较大的不同点之一,这也是一个前C++程序员由衷认为Java可能、或许、maybe要比C++更好用的原因之一。二十多年来,Java一直保持着更新,不断完善并与时俱进,这可能是其多年来独领编程语言之风骚的重要原因。不多扯,入正题。(编程知识的学习,我一般会遵循这样的一个过程:先熟悉基本概念,再来个小程序跑起来看看,最后理论与程序相结合,加深认识并总结记录。)

1、什么是Annotation


Annotation被译作“注解”,标准的英译汉,但是这个译词并没有很好的反映Annotation在java中的意义,或许“标记”更好一些,也或许“标签”。

注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后的某个时刻非常方便地使用这些数据。——《Java编程思想》

注解是那些插入到源代码中使用其他工具可以对其进行处理的标签。——《Java核心技术卷2》

从《Java核心技术卷2》的定义来看,注解包含两点内容:其一,它是标签、标记;此外,这个标签(标记)可以使用其他工具进行处理。
那么,其他工具在哪里可以处理这些标签呢?一个是源码层,另一个是类文件。

注解不会改变程序的编译方式,对于包含注解和不包含注解的代码,Java编译器会生成相同的虚拟机指令。——《Java核心技术卷2》

综上,大致可以给出Java注解一个简单通俗的描述使用过程:定义标签,然后提供标签处理工具,最后是应用标签到其它的代码中。当然,Java自带的注解,我们就只需要直接使用就可以了,因为定义和处理工具Java都帮我们做好了。

2、来个sample


2.1定义标签

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
    
    public int id();
    
    public String description() default "No description";
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
Target和Retention是java语言自带的两个元注解,Target表示用户自定义的注解(UseCase)能应用在哪里(注解类型声明,包,类或接口、方法等);
Retention用来指明自定义注解应该保留多长的时间(取值为SOURCE/CLASS/RUNTIME)
public @interface UseCase
这是定义注解的语法形式,乍一看类似接口的定义,区别在于interface前加了一个@符号,后续使用该用户自定义注解时语法就是@UseCase
public int id();
public String description() default "No description";
这是注解中定义字段的语法,()并不表示这是一个方法,再者,注解中不支持定义方法。
同时,可以设置字段的默认值,通过default关键字。没有默认值的字段必须在使用时显示指明。

2.2 标签处理工具

import java.lang.reflect.*;

public class UseCaseTracker {

    public static void trackUseCase(Class<?> cl) {
        for (Method m : cl.getMethods()) {
            UseCase useCase = m.getAnnotation(UseCase.class);
            if (useCase != null) {
                System.out.println("Found Use Case : " + useCase.id() + " " + useCase.description());
            }
        }
    }

}
@Retention(RetentionPolicy.RUNTIME)中的RUNTIME使得注解可以保留到类文件中,并由虚拟机载入,这样我们就可以通过反射API来获得它们。接下来我就是通过反射API获得这些注解。
public static void trackUseCase(Class<?> cl) {
    for (Method m : cl.getMethods()) {
        UseCase useCase = m.getAnnotation(UseCase.class);
        if (useCase != null) {
            System.out.println("Found Use Case : " + useCase.id() + " " + useCase.description());
        }
    }
}
trackUseCase方法通过传入应用了UseCase注解的类,再通过反射API获得这些注解并打印注解中的信息。    

2.3 应用标签

import java.util.List;

public class PasswordUtils {
    
    @UseCase(id=47, description="Passwords must contain at least one numeric")
    public boolean validatePassword(String password) {
        return (password.matches("\\w*\\d\\w*"));
    }
    
    @UseCase(id=48)
    public String encryptPassword(String password) {
        return new StringBuilder(password).reverse().toString();
    }
    
    @UseCase(id=49, description="New passwords can't equal previously used ones")
    public boolean checkForNewPassword(List<String> prePasswords, String password) {
        return !prePasswords.contains(password);
    }
    
}
@Target(ElementType.METHOD)规定了注解只能是应用在方法上,因此,上述例子中便是如此。
@UseCase(id=47, description="Passwords must contain at least one numeric")
@UseCase(id=48)
@UseCase(id=49, description="New passwords can't equal previously used ones")
以上是三种使用应用自定义注解的例子。

2.4 测试

import java.lang.reflect.*;

public class UseCaseTracker {

    public static void trackUseCase(Class<?> cl) {
        for (Method m : cl.getMethods()) {
            UseCase useCase = m.getAnnotation(UseCase.class);
            if (useCase != null) {
                System.out.println("Found Use Case : " + useCase.id() + " " + useCase.description());
            }
        }
    }
    
    public static void main(String[] args) {
        trackUseCase(PasswordUtils.class);
    }

} 

直接在注解处理工具中加了个main方法来测试注解处理工具。输出结果如下:

Found Use Case : 47 Passwords must contain at least one numeric
Found Use Case : 49 New passwords can't equal previously used ones
Found Use Case : 48 No description

注:以上代码来自《Java编程思想》,部分有改动。

3、归纳整理


3.1 注解元素(属性)的类型

基本类型(int/short/long/byte/char/double/float/boolean)
String
Class
enum
注解类型
以上五种类型组成的数组

注:注解元素值不能为null,默认值也不能为null。

3.2 标准注解

这里写图片描述

3.3 Target注解的元素类型

元素类型定义在枚举类星Element中。
这里写图片描述

3.4 Retention注解的元素类型

这里写图片描述

目录
相关文章
|
4月前
|
Java API 微服务
2025 年 Java 从入门到精通学习笔记全新版
《Java学习笔记:从入门到精通(2025更新版)》是一本全面覆盖Java开发核心技能的指南,适合零基础到高级开发者。内容包括Java基础(如开发环境配置、核心语法增强)、面向对象编程(密封类、接口增强)、进阶技术(虚拟线程、结构化并发、向量API)、实用类库与框架(HTTP客户端、Spring Boot)、微服务与云原生(容器化、Kubernetes)、响应式编程(Reactor、WebFlux)、函数式编程(Stream API)、测试技术(JUnit 5、Mockito)、数据持久化(JPA、R2DBC)以及实战项目(Todo应用)。
240 5
|
1月前
|
小程序 Java 知识图谱
Java 学习笔记 —— BMI & BMR 计算器
这是一个使用 Java 编写的 BMI 与 BMR 计算器小程序,可输入年龄、性别、身高和体重,计算身体质量指数(BMI)和基础代谢率(BMR),并输出健康评估结果。通过该项目,掌握了 Java 的输入处理、数据验证、条件判断、数学运算及格式化输出等基础知识,是 Java 初学者的理想练习项目。
|
29天前
|
Java
Java 数组学习笔记
本文整理Java数组常用操作:遍历、求和、查找、最值及二维数组行求和等典型练习,涵盖静态初始化、元素翻倍、去极值求平均等实例,帮助掌握数组基础与应用。
|
7月前
|
存储 Java
# 【Java全栈学习笔记-U1-day02】变量+数据类型+运算符
本篇笔记主要围绕Java全栈学习的第二天内容展开,涵盖了变量、数据类型、运算符以及Scanner类的应用。首先介绍了变量的概念与命名规范,以及如何定义和使用变量;接着详细讲解了Java中的基本数据类型,包括整型、浮点型、字符型、布尔型等,并通过实例演示了数据类型的运用。随后,深入探讨了各类运算符(赋值、算术、关系、逻辑)及其优先级,帮助理解表达式的构成。最后,介绍了如何利用Scanner类实现用户输入功能,并通过多个综合示例(如计算圆面积、购物打折、变量交换及银行利息计算)巩固所学知识。完成相关作业将进一步加深对这些基础概念的理解与实践能力。
113 13
|
存储 Java
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
288 4
|
7月前
|
开发框架 Java 开发工具
【Java全栈学习笔记-U1-day01】Java介绍
本笔记整理了Java学习的基础内容,涵盖程序理解、Java语言特性、JDK安装与配置、Java程序开发工具及编写步骤。重点介绍了Java程序的基本结构、编译和运行过程,以及输出语句的使用。通过实例演示了IDEA创建Java程序的方法,并强调了编码规范和注意事项。适合初学者复习和交流学习。 主要内容: 1. 理解程序:计算机组成、程序定义。 2. 简介:Java语言特点、技术平台、JDK作用。 3. 编写Java程序:编写、编译、运行步骤,基本结构。 4. 输出语句 5. DEA使用:新建工程、保存位置、文件介绍、新建类。 6. 扩展:注释、代码规范、大小写敏感、缩进等。
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(基础篇)
从Java环境的搭建到实际代码的编写,从基本用法的讲解到底层原理的剖析,深度解析Java基础知识。本文是《Java学习路线》专栏的起始文章,旨在提供一套完整的Java学习路线,覆盖Java基础知识、数据库、SSM/SpringBoot等框架、Redis/MQ等中间件、设计模式、架构设计、性能调优、源码解读、核心面试题等全面的知识点,并在未来不断更新和完善,帮助Java从业者在更短的时间内成长为高级开发。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(基础篇)
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
本文是Java基础的进阶篇,对异常、集合、泛型、Java8新特性、I/O流等知识进行深入浅出的介绍,并附有对应的代码示例,重要的地方带有对性能、底层原理、源码的剖析。适合Java初学者。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
|
11月前
|
Java 数据库连接 API
Spring 框架的介绍(Java EE 学习笔记02)
Spring是一个由Rod Johnson开发的轻量级Java SE/EE一站式开源框架,旨在解决Java EE应用中的多种问题。它采用非侵入式设计,通过IoC和AOP技术简化了Java应用的开发流程,降低了组件间的耦合度,支持事务管理和多种框架的无缝集成,极大提升了开发效率和代码质量。Spring 5引入了响应式编程等新特性,进一步增强了框架的功能性和灵活性。
194 0
|
SQL druid Java
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
156 3
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)

热门文章

最新文章