Java 注解使用教程

简介

Java 1.5 引入了注解,现在它在 Java EE 框架(如 HibernateJerseySpring )中被大量使用。Java 注释是该语言的一个强大特性,用于向 Java 代码中添加元数据。它们不直接影响程序逻辑,但可以由工具、库或框架处理,以执行特定的任务(例如代码生成、验证或自定义处理)。

元注解

目前有五种类型的元注解

@Documented

指示使用此注解的元素应该由 javadoc 和类似的工具记录。该类型应该用于注解类型的声明,这些类型的注解会影响其客户端对已注解元素的使用。如果一个类型声明用 Documented 进行了注解,那么它的注解将成为被注解元素的公共API的一部分。

@Target

表示注解类型适用的程序元素种类。一些可能的值是 TYPE、METHOD、CONSTRUCTOR、FIELD 等。如果不存在目标元注解,则注解可用于任何程序元素。

元素类型对应可以应用的位置:

  • TYPE:类、接口、枚举、记录

  • FIELD:字段、枚举常量

  • METHOD:方法

  • CONSTRUCTOR:构造器

  • LOCAL_VARIABLE:本地变量

  • ANNOTATION_TYPE:注解接口声明

  • PARAMETER:参数声明

  • PACKAGE:包声明

  • TYPE_PARAMETER:类型参数声明

  • TYPE_USE:类型的使用

  • MODULE:模块声明

  • RECORD_COMPONENT:记录组件声明

用法示例

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})  
@interface MyAnnotation{  
    int value1();  
    String value2();  
}  
@Inherited

表示自动继承注解类型。如果用户查询类声明上的注解类型,而类声明没有此类型的注解,则将自动查询该类的超类以获取注解类型。这个过程将重复进行,直到找到该类型的注解,或者到达类层次结构的顶端(Object)

@Retention

表示注解类型的注解要保留多长时间。它采用 RetentionPolicy 枚举中的参数,其可能值为 SOURCE、CLASS 和 RUNTIME

保留策略可用的值:

  • RetentionPolicy.SOURCE:源代码可用,在编译期间被丢弃,它在编译后的类中不可用。

  • RetentionPolicy.CLASSjava 编译器可以访问,但 JVM 无法访问,它包含在 class 文件中。

  • RetentionPolicy.RUNTIME:运行时可用,可供 Java 编译器和 JVM 使用。

@Repeatable

用于指示其注解的类型声明是可重复的。

内建的注解

  • @Override

当想要重写一个 Superclass 的方法时,应该使用这个注解来通知编译器我们正在重写一个方法。因此,当父类方法被删除或更改时,编译器将显示错误消息。

  • @Deprecated

当我们想让编译器知道某个方法已被弃用时,我们应该使用此注释。

  • @SuppressWarnings

这只是为了告诉编译器忽略它们产生的特定警告,例如在 Java 泛型中使用原始类型。它的保留策略是 SOURCE,它会被编译器丢弃。

  • @FunctionalInterface

此注释是在 Java 8 中引入的,用于表明该接口旨在成为一个功能接口。

  • @SafeVarargs

程序员断言,注解方法或构造函数的主体不会对其 varargs 参数执行潜在的不安全操作。

使用元注解和内建注解示例

public class AnnotationExample {
	public static void main(String[] args) {
	}

	@Override
	@MethodInfo(author = "Pankaj", comments = "Main method", date = "Nov 17 2012", revision = 1)
	public String toString() {
		return "Overriden toString method";
	}

	@Deprecated
	@MethodInfo(comments = "deprecated method", date = "Nov 17 2012")
	public static void oldMethod() {
		System.out.println("old method, don't use it.");
	}

	@SuppressWarnings({ "unchecked", "deprecation" })
	@MethodInfo(author = "Pankaj", comments = "Main method", date = "Nov 17 2012", revision = 10)
	public static void genericsTest() throws FileNotFoundException {
		List l = new ArrayList();
		l.add("abc");
		oldMethod();
	}
}

注解的类型

  • 标记注释

没有方法的注解称为标记注解,例如:@Override 和 @Deprecated 是标记注释

@interface MyAnnotation{} 
  • 单值注解

只有一个方法的注解称为单值注解

@interface MyAnnotation{  
    int value() default 0;  
} 

// 应用注解
@MyAnnotation(value=10)  
  • 多值注解

具有多个方法的注释称为多值注释

@interface MyAnnotation{  
    int value1() default 1;  
    String value2() default "";  
    String value3() default "abc";  
}  

// 应用注解
@MyAnnotation(value1=10,value2="Arun Kumar",value3="Ghaziabad")  

自定义注解示例

先定义三个注解

  • JsonSerializable
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface JsonSerializable {
}
  • JsonElement
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonElement {
    String key() default "";
}
  • Init
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Init {
}

接着定义Person实体

import com.redmine.annotationexample.annotation.Init;
import com.redmine.annotationexample.annotation.JsonElement;
import com.redmine.annotationexample.annotation.JsonSerializable;

@JsonSerializable
public class Person {

    @JsonElement
    private String firstName;

    @JsonElement
    private String lastName;

    @JsonElement(key = "personAge")
    private int age;

    private String address;

    @Init
    private void initNames() {
        this.firstName = this.firstName.substring(0, 1).toUpperCase() + this.firstName.substring(1);
        this.lastName = this.lastName.substring(0, 1).toUpperCase() + this.lastName.substring(1);
    }

    public Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
}

定义一个异常类

public class JsonSerializationException extends RuntimeException {
    public JsonSerializationException(String message) {
        super(message);
    }
}

编写注解处理器

import com.redmine.annotationexample.exception.JsonSerializationException;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

public class ObjectToJsonConverter {

    public String convertObjectToJson(Object obj) throws JsonSerializationException {
        try {
            checkIfSerializable(obj);
            initializeObject(obj);
            return getJsonString(obj);
        } catch (Exception e) {
            throw new JsonSerializationException(e.getMessage());
        }
    }

    private void checkIfSerializable(Object obj) {
        if (Objects.isNull(obj)) {
            throw new JsonSerializationException("Object is null");
        }

        Class<?> clazz = obj.getClass();
        if (!clazz.isAnnotationPresent(JsonSerializable.class)) {
            throw new JsonSerializationException("The class" + clazz.getName() + " is not annotated with JsonSerializable");
        }
    }

    private void initializeObject(Object obj) throws Exception {
        Class<?> clazz = obj.getClass();
        for (Method method : clazz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(Init.class)) {
                method.setAccessible(true);
                method.invoke(obj);
            }
        }
    }

    private String getJsonString(Object obj) throws Exception {
        Class<?> clazz = obj.getClass();
        Map<String, String> jsonElementsMap = new HashMap<>();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            if (field.isAnnotationPresent(JsonElement.class)) {
                JsonElement annotation = field.getAnnotation(JsonElement.class);
                String mapKey = !Objects.equals(annotation.key(), "") ? annotation.key() : field.getName();
                jsonElementsMap.put(mapKey, field.get(obj).toString());
            }
        }

        return jsonElementsMap.entrySet()
                .stream()
                .map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"")
                .collect(Collectors.joining(",", "{", "}"));
    }
}

单元测试运行试下

@SpringBootTest
class AnnotationExampleApplicationTests {

    @Test
    void contextLoads() {
    }

    @Test
    void givenObjectSerializedTheTrueReturned() throws JsonSerializationException {
        Person person = new Person("soufiane", "cheouati", 34);
        ObjectToJsonConverter serializer = new ObjectToJsonConverter();
        String jsonString = serializer.convertObjectToJson(person);
        Assertions.assertEquals("{\"personAge\":\"34\",\"firstName\":\"Soufiane\",\"lastName\":\"Cheouati\"}", jsonString);
    }
}

JDK 注解定义

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第17章 读写锁分离设计模式(Java高并发编程详解:多线程与系统设计)

1.场景描述 对资源的访问一般包括两种类型的动作——读和写(更新、删除、增加等资源会发生变化的动作)&#xff0c;如果多个线程在某个时刻都在进行资源的读操作&#xff0c;虽然有资源的竞争&#xff0c;但是这种竞争不足以引起数据不一致的情况发生&#xff0c;那么这个时候…

强化学习 DAY1:什么是 RL、马尔科夫决策、贝尔曼方程

第一部分 RL基础&#xff1a;什么是RL与MRP、MDP 1.1 入门强化学习所需掌握的基本概念 1.1.1 什么是强化学习&#xff1a;依据策略执行动作-感知状态-得到奖励 强化学习里面的概念、公式&#xff0c;相比ML/DL特别多&#xff0c;初学者刚学RL时&#xff0c;很容易被接连不断…

【STM32系列】利用MATLAB配合ARM-DSP库设计FIR数字滤波器(保姆级教程)

ps.源码放在最后面 设计IIR数字滤波器可以看这里&#xff1a;利用MATLAB配合ARM-DSP库设计IIR数字滤波器&#xff08;保姆级教程&#xff09; 前言 本篇文章将介绍如何利用MATLAB与STM32的ARM-DSP库相结合&#xff0c;简明易懂地实现FIR低通滤波器的设计与应用。文章重点不在…

DeepSeek-R1 本地电脑部署 Windows系统 【轻松简易】

本文分享在自己的本地电脑部署 DeepSeek&#xff0c;而且轻松简易&#xff0c;快速上手。 这里借助Ollama工具&#xff0c;在Windows系统中进行大模型部署~ 1、安装Ollama 来到官网地址&#xff1a;Download Ollama on macOS 点击“Download for Windows”下载安装包&#x…

Llama最新开源大模型Llama3.1

Meta公司于2024年7月23日发布了最新的开源大模型Llama 3.1&#xff0c;这是其在大语言模型领域的重要进展。以下是关于Llama 3.1的详细介绍&#xff1a; 参数规模与训练数据 Llama 3.1拥有4050亿&#xff08;405B&#xff09;参数&#xff0c;是目前开源领域中参数规模最大的…

Linux之安装docker

一、检查版本和内核是否合格 Docker支持64位版本的CentOS 7和CentOS 8及更高版本&#xff0c;它要求Linux内核版本不低于3.10。 检查版本 cat /etc/redhat-release检查内核 uname -r二、Docker的安装 1、自动安装 Docker官方和国内daocloud都提供了一键安装的脚本&#x…

2022年全国职业院校技能大赛网络系统管理赛项模块A:网络构建(样题3)-网络部分解析-附详细代码

目录 附录1:拓扑图 附录2:地址规划表 1.SW1 2.SW2 3.SW3 4.SW4 5.SW5 6.SW6 7.SW7 8.R1 9.R2 10.R3 11.AC1 12.AC2 13.AP2 14.AP3 15.EG1 16.EG2 附录1:拓扑图 附录2:地址规划表 设备

Vim跳转文件及文件行结束符EOL

跳转文件 gf 从当前窗口打开那个文件的内容&#xff0c;操作方式&#xff1a;让光标停在文件名上&#xff0c;输入gf。 Ctrlo 从打开的文件返回之前的窗口 Ctrlwf 可以在分割的窗口打开跳转的文件&#xff0c;不过在我的实验不是次次都成功。 统一行尾格式 文本文件里存放的…

《Angular之image loading 404》

前言&#xff1a; 千锤万凿出深山&#xff0c;烈火焚烧若等闲。 正文&#xff1a; 一。问题描述 页面加载图片&#xff0c;报错404 二。问题定位 页面需要加载图片&#xff0c;本地开发写成硬编码的形式请求图片资源&#xff1a; 然而部署到服务器上报错404 三。解决方案 正确…

Windows Docker笔记-Docker容器操作

在文章《Windows Docker笔记-Docker拉取镜像》中&#xff0c;已经拉取成功了ubuntu镜像&#xff0c;本章来讲解如何通过镜像来创建容器并运行容器。 这里再类比一下&#xff0c;加深理解&#xff0c;比如&#xff0c;我们现在想开一个玩具厂&#xff0c;我们的最终目的肯定是想…

upload-labs安装与配置

前言 作者进行upload-labs靶场练习时&#xff0c;在环境上出了很多问题&#xff0c;吃了很多苦头&#xff0c;甚至改了很多配置也没有成功。 upload-labs很多操作都是旧时代的产物了&#xff0c;配置普遍都比较老&#xff0c;比如PHP版本用5.2.17&#xff08;还有中间件等&am…

(2025|ICLR,音频 LLM,蒸馏/ALLD,跨模态学习,语音质量评估,MOS)音频 LLM 可作为描述性语音质量评估器

Audio Large Language Models Can Be Descriptive Speech Quality Evaluators 目录 1. 概述 2. 研究背景与动机 3. 方法 3.1 语音质量评估数据集 3.2 ALLD 对齐策略 4. 实验结果分析 4.1 MOS 评分预测&#xff08;数值评估&#xff09; 4.2 迁移能力&#xff08;在不同…

深入理解linux中的文件(下)

目录 一、语言级缓冲区和内核级缓冲区 二、C语音中的FILE* fp fopen(“./file.txt”,"w"): 四、理解磁盘结构&#xff1a; 物理结构 逻辑结构 五、未被打开的文件&#xff1a; 六、更加深入理解inode编号怎么找到文件&#xff1a; 七、对路径结构进行…

零基础Vue入门6——Vue router

本节重点&#xff1a; 路由定义路由跳转 前面几节学习的都是单页面的功能&#xff08;都在专栏里面https://blog.csdn.net/zhanggongzichu/category_12883540.html&#xff09;&#xff0c;涉及到项目研发都是有很多页面的&#xff0c;这里就需要用到路由&#xff08;vue route…

京准:NTP卫星时钟服务器对于DeepSeek安全的重要性

京准&#xff1a;NTP卫星时钟服务器对于DeepSeek安全的重要性 京准&#xff1a;NTP卫星时钟服务器对于DeepSeek安全的重要性 在网络安全领域&#xff0c;分布式拒绝服务&#xff08;DDoS&#xff09;攻击一直是企业和网络服务商面临的重大威胁之一。随着攻击技术的不断演化…

网络计算机的五个组成部分

单个计算机是无法进行通信的。所以需要借助网络。 下面介绍一些在网络里常见的设备。 一、服务器 服务器是在网络环境中提供计算能力并运行软件应用程序的特定IT设备 它在网络中为其他客户机&#xff08;如个人计算机、智能手机、ATM机等终端设备&#xff09;提供计算或者应用…

MATLAB实现单层竞争神经网络数据分类

一.单层竞争神经网络介绍 单层竞争神经网络&#xff08;Single-Layer Competitive Neural Network&#xff09;是一种基于竞争学习的神经网络模型&#xff0c;主要用于数据分类和模式识别。其核心思想是通过神经元之间的竞争机制&#xff0c;使得网络能够自动学习输入数据的特…

【漫画机器学习】082.岭回归(或脊回归)中的α值(alpha in ridge regression)

岭回归&#xff08;Ridge Regression&#xff09;中的 α 值 岭回归&#xff08;Ridge Regression&#xff09;是一种 带有 L2​ 正则化 的线性回归方法&#xff0c;用于处理多重共线性&#xff08;Multicollinearity&#xff09;问题&#xff0c;提高模型的泛化能力。其中&am…

网络安全 | 零信任架构:重构安全防线的未来趋势

网络安全 | 零信任架构&#xff1a;重构安全防线的未来趋势 一、前言二、零信任架构的核心概念与原理2.1 核心概念2.2 原理 三、零信任架构的关键技术组件3.1 身份管理与认证系统3.2 授权与访问控制系统3.3 网络与安全监测系统3.4 加密与数据保护技术 四、零信任架构与传统安全…

网络爬虫学习:借助DeepSeek完善爬虫软件,增加停止任务功能

一、引言 我从24年11月份开始学习网络爬虫应用开发&#xff0c;经过2个来月的努力&#xff0c;终于完成了开发一款网络爬虫软件的学习目标。这几天对本次学习及应用开发进行一下回顾总结。前面已经发布了两篇日志&#xff1a; 网络爬虫学习&#xff1a;应用selenium从搜*狐搜…