【Java高级语法】(十三)注解:解码程序设计中的元数据利器,在小小的@符里挖呀挖呀挖~用小小的注解做强大的开发...

news2025/1/2 3:36:12

Java高级语法详解之注解

  • 1️⃣ 概念
  • 2️⃣ 优势和缺点
  • 3️⃣ 使用
    • 3.1 元注解
    • 3.2 自定义注解
    • 3.3 常用内置注解
  • 4️⃣ 应用场景
  • 5️⃣ 扩展:那些流行框架中的注解
  • 🌾 总结

在这里插入图片描述

1️⃣ 概念

Java 注解(Annotation) 是Java语言中一种元数据形式,它提供了一种在代码中添加元数据的方式。注解为程序员提供了向代码中添加额外信息的能力,这些额外信息可以被编译器、工具或者运行时环境使用。

2️⃣ 优势和缺点

优点:

  • 提供了一种更加简洁和可读性强 的代码编写风格;
  • 增强代码的可维护性和可重用性,通过使用注解可以减少重复的代码;
  • 可以帮助开发者在编译时检测错误,提高代码的健壮性。

缺点:

  • 过度使用注解会使代码变得复杂和难以理解;
  • 注解的滥用可能导致代码过于依赖于特定的框架或工具,降低了代码的可移植性;
  • 注解可能增加代码的复杂性,并且可能需要花费更多的时间来学习和理解其使用方式。

3️⃣ 使用

3.1 元注解

元注解也是一种注解,用于对其他注解进行注释。Java提供了几种元注解,用于自定义和修饰注解声明,包括以下几种:

  • @Retention:指定注解的生命周期,可选值包括SOURCECLASSRUNTIME
  • @Target:指定注解可以应用的目标元素类型,如类、方法、字段等;
  • @Documented:指定注解是否包含在API文档中;
  • @Inherited:指定子类是否继承父类的注解;
  • @Repeatable:指定该注解可以被多次应用于同一元素。

3.2 自定义注解

在Java中,我们可以自定义注解,以满足特定的需求。自定义注解使用@interface关键字进行声明。

下面是一个使用上文元注解的简单演示案例程序,展示了如何在Java中应用这些注解来自定义一个注解:

import java.lang.annotation.*;

// 定义一个自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Inherited
@Repeatable(MyAnnotations.class)
@interface MyAnnotation {
    String value() default "";
}

// 定义一个可重复注解容器
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotations {
    MyAnnotation[] value();
}

// 使用自定义注解
@MyAnnotation("Class Annotation")
public class DemoClass {

    @MyAnnotation("Field Annotation")
    private String field;

    @MyAnnotation("Constructor Annotation")
    public DemoClass() {
        // 构造函数注解
    }

    @MyAnnotation("Method Annotation")
    public void demoMethod() {
        // 方法注解
    }

    public static void main(String[] args) {
        DemoClass obj = new DemoClass();
        Class<? extends DemoClass> clz = obj.getClass();

        // 获取类上的注解
        MyAnnotation classAnnotation = clz.getAnnotation(MyAnnotation.class);
        System.out.println("Class Annotation: " + classAnnotation.value());

        // 获取字段上的注解
        try {
            java.lang.reflect.Field field = clz.getDeclaredField("field");
            MyAnnotation fieldAnnotation = field.getAnnotation(MyAnnotation.class);
            System.out.println("Field Annotation: " + fieldAnnotation.value());
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        // 获取构造函数上的注解
        try {
            java.lang.reflect.Constructor<?> constructor = clz.getDeclaredConstructor();
            MyAnnotation constructorAnnotation = constructor.getAnnotation(MyAnnotation.class);
            System.out.println("Constructor Annotation: " + constructorAnnotation.value());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        // 获取方法上的注解
        try {
            java.lang.reflect.Method method = clz.getDeclaredMethod("demoMethod");
            MyAnnotation methodAnnotation = method.getAnnotation(MyAnnotation.class);
            System.out.println("Method Annotation: " + methodAnnotation.value());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

这段代码演示了如何定义和使用自定义注解,并从类、字段、构造函数和方法中获取注解的值。

首先,我定义了一个自定义注解 @MyAnnotation。注解的定义可以通过多个元注解修饰,这些元注解用于为注解提供额外的信息:

  • @Retention(RetentionPolicy.RUNTIME):指定注解保留的生命周期为运行时。这意味着注解将在运行时仍然可见,可以通过 Java 反射机制获取;
  • @Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR}):指定注解可以应用于类、字段、方法和构造函数上;
  • @Documented:指定该注解将包含在 Javadoc 中;
  • @Inherited:指定子类默认继承父类的注解。

之后,在 DemoClass 类上、类中的字段、构造函数和方法上都使用了自定义注解 @MyAnnotation

main 方法中,首先创建了一个 DemoClass 对象 obj,通过反射获取 DemoClass 类的实例对象的运行时类型以及类上的注解。

接着,通过反射机制分别获取字段上的注解、构造函数上的注解、方法上的注解。并且打印了相应注解的值,以演示如何从类、字段、构造函数和方法中获取注解的值。

通过自定义注解,我们可以根据需要添加元数据,并在代码中使用它。

3.3 常用内置注解

Java提供了很多内置的注解,我们来介绍几个常用的注解:

  • @Override:用于标记方法覆写(重写)父类的方法,可以帮助我们检查是否正确地覆写了方法;
  • @Deprecated:用于标记过时的方法或类,在程序中使用过时的元素会收到警告提示,鼓励使用更合适的替代方案;
  • @SuppressWarnings:用于抑制编译器产生的警告信息,可以让代码看起来更整洁,但需谨慎使用;
  • @FunctionalInterface:用于标记函数式接口(只有一个抽象方法),可以确保接口的语义符合函数式编程的要求。

下面是一个使用Java实现的演示案例程序,展示了如何使用@Override@Deprecated@SuppressWarnings@FunctionalInterface注解:

import java.util.ArrayList;
import java.util.List;

class Parent {
    public void display() {
        System.out.println("Parent class");
    }
}

class Child extends Parent {
    @Override
    public void display() {
        System.out.println("Child class");
    }
}

@Deprecated
class DeprecatedClass {
    @Deprecated
    public void deprecatedMethod() {
        System.out.println("\nThis method is deprecated.");
    }
}

@SuppressWarnings("unused")
class SuppressWarningsClass {
    // unused field
    private int unusedVariable;

    @SuppressWarnings("unchecked")
    public void suppressWarningsMethod() {
        List list = new ArrayList();
        list.add("item");
        System.out.println("\n" + list);
    }
}

@FunctionalInterface
interface FunctionalInterfaceExample {
    void someMethod();
}

public class AnnotationDemo {
    public static void main(String[] args) {
        // @Override example
        Parent parent = new Parent();
        Child child = new Child();

        parent.display();           // Output: Parent class
        child.display();            // Output: Child class

        // @Deprecated example
        DeprecatedClass  deprecatedObject = new DeprecatedClass();
        deprecatedObject.deprecatedMethod();  // Output: This method is deprecated.

        // @SuppressWarnings example
        SuppressWarningsClass suppressWarningsObject = new SuppressWarningsClass();
        suppressWarningsObject.suppressWarningsMethod();  // No warning will be generated

        // @FunctionalInterface example
        FunctionalInterfaceExample functionalInterfaceObject = () -> System.out.println("\nFunctional Interface");
        functionalInterfaceObject.someMethod();  // Output: Functional Interface
    }
}

在这个示例程序中,我们创建了Parent类和Child类,其中Child类使用@Override注解来标记覆写(重写)了Parent类中的display()方法。这样在编译时,如果有错误地覆写了父类的方法,编译器将会给出错误提示。

另外,我们还创建了一个名为DeprecatedClass的过时类,并在其中的方法和类声明上都使用了@Deprecated注解。当我们在程序中使用过时的方法或类时,编译器会发出警告,鼓励我们使用更合适的替代方案。

同样,我们还创建了一个名为SuppressWarningsClass的类,在该类的方法和字段上使用了@SuppressWarnings注解来抑制编译器产生的警告信息,以便让代码看起来更整洁。但是需要注意,谨慎使用此注解,确保其使用场景合理。

再者,我们创建了一个函数式接口FunctionalInterfaceExample,并使用@FunctionalInterface注解进行标记。这个注解可以确保该接口只有一个抽象方法,从而符合函数式编程的要求。

最后,在main方法中展示了如何使用这些注解的例子,运行程序验证结果如下:

Parent class
Child class

This method is deprecated.

[item]

Functional Interface

4️⃣ 应用场景

Java注解广泛应用于各个领域,包括但不限于以下几个方面:

  • 标记/标识:注解可以用于对类、方法、字段等进行标记,以便将来在编译期、运行时或工具处理期间根据标记进行特定操作;
  • 配置/设置:注解可以用于配置代码,在运行时根据注解的参数动态地控制程序的行为;
  • 生成代码/文档:通过使用注解,可以自动生成代码、配置文件或文档等。

5️⃣ 扩展:那些流行框架中的注解

在各个流行框架中,注解都起着重要的作用。它们为开发者提供了一种简洁、灵活和快速的方式来配置和扩展应用程序。

下面列举了一些主要流行框架中注解的应用范例:

  1. Spring

    • @Component:标记类为一个可被Spring容器管理的组件;
    • @Controller:标记控制器类,用于处理用户请求;
    • @RequestMapping:在控制器方法上定义路由规则与请求的映射关系;
    • @Service:标记服务层类,在业务逻辑中使用;
    • @Repository:标记数据访问层类,使得 Spring 可以自动将其纳入到 bean 容器;
    • @Autowired:自动将依赖注入到相应的类中,简化了组件间的耦合关系;
    • @Configuration:标记类为Spring配置类;
    • @Bean:标记方法返回值为Spring Bean,并由容器管理。
  2. Spring Boot

    • @SpringBootApplication:标记引导类,表示一个 Spring Boot 应用程序入口点;
    • @RestController:结合了 @Controller@ResponseBody,用于构建 RESTful API 控制器;
    • @RequestMapping:指定请求的 URL 路径和 HTTP 方法与方法的映射关系;
    • @ConfigurationProperties:绑定属性文件或环境变量到 Java Bean,方便地进行配置管理;
    • @EnableAutoConfiguration:启用自动配置,根据类路径下的依赖和规则推断、添加 Bean。
  3. Spring Cloud

    • @EnableDiscoveryClient:启用服务发现;
    • @EnableCircuitBreaker:启用断路器;
    • @FeignClient:声明一个可调用远程服务的客户端接口;
    • @EnableZuulProxy:启用Zuul代理网关;
    • @LoadBalanced:启用负载均衡客户端。
  4. Spring MVC

    • @Controller:标记类为MVC控制器;
    • @RequestMapping:将请求映射到控制器的方法上;
    • @RequestParam:将请求参数映射到方法参数上;
    • @PathVariable:将URL路径变量映射到方法参数上;
    • @ResponseBody:将方法返回值序列化成响应主体。
  5. MyBatis

    • @Mapper:标记接口为MyBatis的映射器;
    • @Select:定义查询语句;
    • @Insert:定义插入语句;
    • @Update:定义更新语句;
    • @Delete:定义删除语句;
    • @Param:指定方法参数与SQL语句中的参数对应关系等。
  6. Hibernate

    • @Entity:声明实体类;
    • @Table:指定实体类与数据库表之间的映射关系;
    • @Column:定义属性与数据库列之间的映射关系;
    • @Id:标识实体类的主键属性;
    • @GeneratedValue:指定主键生成策略;
    • @ManyToOne:定义多对一关系。
  7. Junit

    • @Test:标记测试方法;
    • @Before:在每个测试方法执行前被执行的方法;
    • @After:在每个测试方法执行后被执行的方法;
    • @RunWith:指定测试运行器,如使用 Spring 进行测试时可以指定 @RunWith(SpringRunner.class)
    • @BeforeEach:在每个测试方法之前运行的方法(JUnit 5);
    • @AfterEach:在每个测试方法之后运行的方法(JUnit 5);
    • @ParameterizedTest:参数化测试方法(JUnit 5)。

注解在这些框架中广泛应用,通过提供特定的注解,开发者可以方便地实现配置、路由、依赖注入、持久化等相关功能,大大简化了开发过程。同时,注解也为框架提供了更好的扩展性和灵活性。

🌾 总结

Java注解提供了一种简洁、灵活和强大的方式来为代码添加额外的元数据信息。它们能够提高代码的可读性、可维护性和健壮性。尽管有一些缺点,但合理地使用注解将带来很多好处。随着时间的推移,注解已经成为许多流行框架和库的核心组成部分。


在这里插入图片描述

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

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

相关文章

chatgpt赋能python:Python爬虫速度分析:如何加速你的爬虫?

Python爬虫速度分析&#xff1a;如何加速你的爬虫&#xff1f; Python作为一种优秀的胶水语言&#xff0c;被广泛应用于web开发、数据处理等众多领域。在众多应用场景中&#xff0c;Python爬虫无疑是其中之一。然而&#xff0c;在爬取海量数据时&#xff0c;爬虫的速度往往成为…

Arthas原理分析

在日常开发中&#xff0c;经常会使用到arthas排查线上问题&#xff0c;觉得arthas的功能非常强大&#xff0c;所以打算花了点时间了解一下其实现原理。并试着回答一下使用Arthas时存在的一些疑问。 Arthas主要基于是Instrumentation JavaAgent Attach API ASM 反射 OGNL等…

chatgpt赋能python:Python点的用法

Python点的用法 作为一名有着10年Python编程经验的工程师&#xff0c;我发现很多初学者对Python的点(.)用法存在疑惑。因此&#xff0c;在这篇文章中&#xff0c;我将详细介绍Python点的用法&#xff0c;并希望能够对这个问题有一个全面的认识。 什么是点 在Python中&#x…

Linux Xshell配置public key实现免密登录linux服务器

linux服务器安装成功后&#xff0c;登录linux服务器的工具有很多中&#xff0c;例如&#xff1a;Xshell、SecureCRT等等。而我所服务的用户使用xshell工具来对linux服务器进行运维。 当使用xshell登录linux服务器时&#xff0c;xshell提供了三种身份验证方式&#xff1a; 1.P…

实战:Maven构建工具实践-2023.6.21(测试成功)

实战&#xff1a;Maven构建工具实践-2023.6.21(测试成功) 目录 推荐文章 https://www.yuque.com/xyy-onlyone/aevhhf?# 《玩转Typora》 实验环境 gitlab/gitlab-ce:15.0.3-ce.0 jenkins/jenkins:2.346.3-2-lts-jdk11 apache-maven-3.9.2 openjdk 11.0.18实验软件 链接&…

对centOS的home目录进行扩容。

对centos的home目录进行扩容 1 首先要了解PV\VG\LV的含义1.1 基本概念1.2 基本命令行 2 实际操作2.1 盘符当前现状2.1实操 1 首先要了解PV\VG\LV的含义 1.1 基本概念 物理卷&#xff08;Physical Volume&#xff0c;PV&#xff09; 指磁盘分区或从逻辑上与磁盘分区具有同样功能…

SPSS统计教程:卡方检验

本文简要的介绍了卡方分布、卡方概率密度函数和卡方检验&#xff0c;并通过SPSS实现了一个卡方检验例子&#xff0c;不仅对结果进行了解释&#xff0c;而且还给出了卡方、自由度和渐近显著性的计算过程。本文用到的数据"2.2.sav"链接为: https://url39.ctfile.com/f/…

菲涅尔圆孔衍射matlab完整程序分享

根据惠更斯 &#xff0d; 菲涅耳原理&#xff0c;光的衍射是光束内部的次波之间的相干叠加&#xff0c;衍射光波场的光振动符合菲涅耳积分公式。但直接运用菲涅耳积分公式计算衍射光场是很困难的。对于夫琅和费衍射(远场衍射)&#xff0c;在光源和接收屏距离衍射屏均为无穷远的…

实战:k8s证书续签-2023.6.19(测试成功)

实战&#xff1a;k8s证书续签-2023.6.19(测试成功) 目录 推荐文章 https://www.yuque.com/xyy-onlyone/aevhhf?# 《玩转Typora》 1、前言 k8s集群核心的证书有2套&#xff0c;还有1套非核心的(即使出问题也问题不大)。 ⚠️ 如果是kubeadm搭建的k8s集群&#xff0c;其有效期为…

chatgpt赋能python:Python烧录单片机:快速的开发工具

Python烧录单片机&#xff1a;快速的开发工具 简介 Python是一种高级的编程语言&#xff0c;被广泛应用于各种领域&#xff0c;包括机器学习、数据分析和物联网等领域。Python的易用性和简洁性已经成为其成功的关键因素之一。Python也能在烧录单片机时提供极大的方便性和灵活…

chatgpt赋能python:用Python自动爬取链接的内容——提升SEO效果的利器

用Python自动爬取链接的内容——提升SEO效果的利器 在当今数字化时代&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;对于任何一个网站来说都至关重要。一种有用的SEO策略就是频繁地更新网站内容&#xff0c;吸引更多的访问者和搜索引擎爬虫。而最快捷的方法就是自动爬取…

chatgpt赋能python:Python爬虫解密:如何快速抓取网站数据

Python爬虫解密&#xff1a;如何快速抓取网站数据 在当今信息时代&#xff0c;人们越来越依赖互联网获取信息。不同的网站提供了大量数据&#xff0c;但是手动去抓取这些数据十分困难&#xff0c;效率也很低。Python爬虫技术是解决这一问题的有效工具之一&#xff0c;它可以帮…

使用npm安装pnpm包管理器

使用npm安装pnpm包管理器 一、安装 使用 npm install pnpm -g 命令安装pnpm npm install pnpm -g安装完成之后&#xff0c;使用pnpm -v命令查询是否成功安装&#xff0c;出现版本号即可 二、设置源 1.先查看源是否为淘宝的源 pnpm config get registry 2.设置源命令 pn…

TS:pip安装python库报ssl错误-2023.6.17(已解决)

2023.6.17-TS-pip安装python库报ssl错误(已解决) 目录 文章目录 2023.6.17-TS-pip安装python库报ssl错误(已解决)目录报错现象报错环境测试过程换其他源还是报错&#xff08;失败&#xff09;百度&#xff1a;替换为豆瓣源并加--trusted-host参数(成功) 参考文章关于我最后 报错…

一文理解多线程机制和多线程的优缺点

一文理解多线程机制 前言&#xff1a;多线程的优缺点。一、什么是多线程1.1、多线程的概念和基本原理1.2、多线程与单线程的区别 二、多线程的应用场景三、C 中的多线程3.1、C11 新增加的 thread 库3.2、C 线程同步机制&#xff08;mutex、condition_variable&#xff09; 四.、…

【Openvino01】Ubuntu安装inter的openvino2022.1以及遇到的各种错误解决

交代一下今天的文章背景&#xff1a; 于最近要使用inter的一款名为Intel Movidius™ Myriad™ X 的加速卡去实现对算法模型的加速推理能力&#xff0c;由于是就得第一步安装openvino&#xff0c;然后再使用卡去验证openvino是否安装ok&#xff0c;卡是否真的存在推理加速的能力…

python pytorch教程-带你从入门到实战(代码全部可运行)

python pytorch教程-带你从入门到实战&#xff08;代码全部可运行&#xff09; 其实这个教程以前博主写过一次&#xff0c;不过&#xff0c;这回再写一次&#xff0c;打算内容写的多一点&#xff0c;由浅入深&#xff0c;然后加入一些实践案例。 下面是我们的内容目录&#x…

2022(一等奖)D1073基于Himawari-8卫星遥感的黑龙江省地表水时空格局研究

作品介绍 1 项目简介 为探究黑龙江省地表水空间格局变化&#xff0c;本项目以黑龙江省为例&#xff0c;基于高时相Himawari-8号卫星数据&#xff0c;通过影像预处理、特征指数选择、自动阈值分类、集成学习和随机森林分类等步骤&#xff0c;融合IDL二次开发与GIS空间分析&…

chatgpt赋能python:Python求绝对值的三种方法

Python 求绝对值的三种方法 Python是一门面向对象、解释型、动态类型的高级编程语言&#xff0c;它被广泛应用于各种领域&#xff0c;特别是科学计算、数据分析、机器学习等领域。在Python中&#xff0c;求绝对值是一个常见的数学操作。本文将介绍Python求绝对值的三种方法&am…

Redis原理 - Redis网络模型

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis原理 - Redis网络模型 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-netword-model.html 思考 Redis 到底是单线程还是多线程&#xff1f; 如果仅仅针对 Redis 的核心业务部分&#xff08;命…