⛳ Java注解

news2024/11/21 11:02:52

目录

  • ⛳ Java注解
    • 🏭 一,常见的注解
    • 🎨 二,JDK元注解
    • 🚜 三,通过反射获取注解
      • 🐾 3.1、JDK常用注解
      • 👣 3.2、简单注解
      • 📢 3.3、复杂注解

⛳ Java注解

  • 从 JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是Annotation(注解)
  • Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理。通过使用 Annotation, 程序员可以在不改变原有逻辑的情况下, 在源文件中嵌入一些补充信息。 代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。
  • Annotation 可以像修饰符一样被使用, 可用于修饰包,类, 构造器, 方法, 成员变量, 参数, 局部变量的声明, 这些信息被保存在Annotation的 “name=value” 对中。
  • 在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE/Android中注解占据了更重要的角色,例如用来配置应用程序的任何切面, 代替JavaEE旧版中所遗留的繁冗代码和XML配置等。
  • 未来的开发模式都是基于注解的, JPA是基于注解的, Spring2.5以上都是基于注解的, Hibernate3.x以后也是基于注解的,现在的Struts2有一部分也是基于注解的了,注解是一种趋势,一定程度上可以说: 框架 = 注解 + 反射 + 设计模式
  • 使用 Annotation 时要在其前面增加 @ 符号, 并把该 Annotation 当成一个修饰符使用。 用于修饰它支持的程序元素

🏭 一,常见的注解

  • @Override: 限定重写父类方法, 该注解只能用于方法
  • @Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择
  • @SuppressWarnings: 抑制编译器警告
public class AnnotationTest{
     public static void main(String[] args) {
         @SuppressWarnings("unused")
         int a = 10;
     }
     @Deprecated
     public void print(){
         System.out.println("过时的方法");
     }
     @Override
     public String toString() {
         return "重写的toString方法()";
     }
 }

🎨 二,JDK元注解

  • JDK 的元 Annotation 用于修饰其他 Annotation 定义

  • JDK5.0提供了4个标准的meta-annotation类型, 分别是:

    • Retention (保持,保留)
    • Target (目标,指标)
    • Documented (备有证明文件的)
    • Inherited (遗传的;继承)
  • @Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 的生命周期, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用@Retention 时必须为该 value 成员变量指定值:

    • RetentionPolicy.SOURCE:在源文件中有效(即源文件保留) , 编译器直接丢弃这种策略的注释
    • RetentionPolicy.CLASS:在class文件中有效(即class保留) , 当运行 Java 程序时, JVM不会保留注解。 这是默认值
    • RetentionPolicy.RUNTIME:在运行时有效(即运行时保留) , 当运行 Java 程序时, JVM 会保留注释。程序可以通过反射获取该注释。
  • @Target: 用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于修饰哪些程序元素。 @Target 也包含一个名为 value 的成员变量。

  • JDK1.8@Target新增类型如下:

    • ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中(如: 泛型声明) 。
    • ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中。
  • Java 8新增可重复注解:

  • @Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被javadoc 工具提取成文档。 默认情况下, javadoc是不包括注解的。

    • 定义为Documented的注解必须设置Retention值为RUNTIME。
  • @Inherited: 被它修饰的 Annotation 将具有继承性。如果某个类使用了被@Inherited 修饰的 Annotation, 则其子类将自动具有该注解。

    • 比如:如果把标有@Inherited注解的自定义的注解标注在类级别上,子类则可以继承父类类级别的注解

🚜 三,通过反射获取注解

  • JDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口, 该接口代表程序中可以接受注解的程序元素

  • 当一个 Annotation 类型被定义为运行时 Annotation 后, 该注解才是运行时可见, 当 class 文件被载入时保存在 class 文件中的 Annotation 才会被虚拟机读取

  • 程序可以调用 AnnotatedElement对象的如下方法来访问 Annotation 信息

    image-20230807102228960

🐾 3.1、JDK常用注解

Person:

package org.example.a_often_annotation;

public class Parent {


    @SuppressWarnings("unused")  // 抑制编译器警告
    public void f1(){
        System.out.println("parent f1");
    }

    @Deprecated   // 用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰的结构危险或者存在了更好的选择
    public void  f2(){
        System.out.println("parent f2");
    }


    public static void main(String[] args) {
        @SuppressWarnings("unused")
        int i = 123;

        Children children = new Children();
        children.f1();
        children.f2();

    }

}

children:

package org.example.a_often_annotation;

public class Children extends Parent{

    @Override
    public void f1() {
        System.out.println("children f1");
    }

    @Override
    public void f2() {
        System.out.println("children f2");
    }

    @Override
    public String toString() {
        return "Children{}";
    }
}

👣 3.2、简单注解

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface MyAnnotation {

}

使用注解:

package org.example.b_simple_annotation;

public class Person {

    @MyAnnotation
    private String name;

    @MyAnnotation
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @MyAnnotation
    public void show(){
        System.out.println("person -> show");
    }

    @MyAnnotation
    public void display(){
        System.out.println("person -> display");
    }
}

测试:

package org.example.b_simple_annotation;

import org.junit.Test;

import java.lang.reflect.Method;

public class TestAnnotation {

    /**
     *  反射调用类中的方法
     */
    @Test
    public void test1(){
        try {
            Class<?> personClass = Class.forName("org.example.b_simple_annotation.Person");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method show = personClass.getMethod("show");
            show.invoke(personBean);  // 调用反射方法
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 注解调用方法
     */
    @Test
    public void test2(){
        try {
            Class<?> personClass = Class.forName("org.example.b_simple_annotation.Person");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例

            // 方法有注解@MyAnnotation执行,没有的不执行
            Method[] methods = personClass.getMethods(); // 得到所有的方法
            for (int i = 0; i < methods.length; i++) {
                if(methods[i].isAnnotationPresent(MyAnnotation.class)){
                    methods[i].invoke(personBean);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

📢 3.3、复杂注解

注解:

package org.example.c_complex_annotation;

import java.lang.annotation.*;

@Inherited  // 表示如果有类使用该注解,这个类的所有子类也自动继承该注解
@Repeatable(MyAnnotations.class)   // 表示该注解在一个地方可以重复出现,实际上是多个该注解合成一个MyAnnotations注解
@Retention(RetentionPolicy.RUNTIME)   // 用于指定该 Annotation 的生命周期,runtime表示运行时保留
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface ComplexAnnotation {

    String value() default "value的初始值";

}



package org.example.c_complex_annotation;

import java.lang.annotation.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface ComplexAnnotation2 {

}



package org.example.c_complex_annotation;


import java.lang.annotation.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface MyAnnotations {

    ComplexAnnotation[] value();

}

用例:

package org.example.c_complex_annotation;

public class CPerson {

    private String name;

    private int age;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @ComplexAnnotation(value = "hello show")
    public void show(){
        System.out.println("CPerson -> show");
    }

    @ComplexAnnotation
    public void display(){
        System.out.println("CPerson -> display");
    }

//    @MyAnnotations({@ComplexAnnotation("hello f2-1"),@ComplexAnnotation("hello f2-2")})  // 等价于下面两个@ComplexAnnotation注解
    @ComplexAnnotation("hello f2-1")
    @ComplexAnnotation("hello f2-2")
    @ComplexAnnotation2
    public void f2(){
        System.out.println("CPerson -> f2");
    }
}

测试:

package org.example.c_complex_annotation;

import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class CTestAnnotation {

    @Test
    public void test1(){
        try {
            Class<?> personClass = Class.forName("org.example.c_complex_annotation.CPerson");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method show = personClass.getMethod("show");
            show.invoke(personBean);  // 调用反射方法  结果:CPerson -> show
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *  得到方法上的所有注解
     */
    @Test
    public void test2(){
        try {
            Class<?> personClass = Class.forName("org.example.c_complex_annotation.CPerson");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method f2 = personClass.getMethod("f2");
            Annotation[] annotations = f2.getAnnotations();
            for (int i = 0; i < annotations.length; i++) {
                System.out.println(annotations[i]);
                /**
                 *  结果:
                 *      @org.example.c_complex_annotation.MyAnnotations(value=[@org.example.c_complex_annotation.ComplexAnnotation(value=hello f2-1), @org.example.c_complex_annotation.ComplexAnnotation(value=hello f2-2)])
                 *      @org.example.c_complex_annotation.ComplexAnnotation2()
                 */
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到方法上的特定注解的值
     */
    @Test
    public void test3(){
        try {
            Class<?> personClass = Class.forName("org.example.c_complex_annotation.CPerson");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method show = personClass.getMethod("show");
            ComplexAnnotation annotation = show.getAnnotation(ComplexAnnotation.class);
            System.out.println(annotation.value());  // 结果:hello show
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到方法上的特定注解的值
     */
    @Test
    public void test4(){
        try {
            Class<?> personClass = Class.forName("org.example.c_complex_annotation.CPerson");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method display = personClass.getMethod("display");
            ComplexAnnotation annotation = display.getAnnotation(ComplexAnnotation.class);
            System.out.println(annotation.value());  // 结果:value的初始值
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

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

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

相关文章

python --windows获取启动文件夹路径/获取当前用户名/添加自启动文件

如何使用Python获取计算机用户名 一、Python自带的getpass模块可以用于获取用户输入的密码&#xff0c;但是它同样可以用来获取计算机用户名。 import getpassuser getpass.getuser() print("计算机用户名为&#xff1a;", user)二、使用os模块获取用户名 Python的…

深度学习部署:FastDeploy部署教程(CSharp版本)

FastDeploy部署教程(CSharp版本) 1. FastDeploy介绍 FastDeploy是一款全场景、易用灵活、极致高效的AI推理部署工具&#xff0c; 支持云边端部署。提供超过 &#x1f525;160 Text&#xff0c;Vision&#xff0c; Speech和跨模态模型&#x1f4e6;开箱即用的部署体验&#xf…

[机器学习]线性回归模型

线性回归 线性回归&#xff1a;根据数据&#xff0c;确定两种或两种以上变量间相互依赖的定量关系 函数表达式&#xff1a; y f ( x 1 , x 2 . . . x n ) y f(x_1,x_2...x_n) yf(x1​,x2​...xn​) ​ 回归根据变量数分为一元回归[ y f ( x ) yf(x) yf(x)]和多元回归[ y …

CSS 属性计算过程

CSS 属性计算过程 你是否了解 CSS 的属性计算过程呢&#xff1f; 有的同学可能会讲&#xff0c;CSS属性我倒是知道&#xff0c;例如&#xff1a; p{color : red; }上面的 CSS 代码中&#xff0c;p 是元素选择器&#xff0c;color 就是其中的一个 CSS 属性。 但是要说 CSS 属…

国内大模型在局部能力上已超ChatGPT

中文大模型正在后来居上&#xff0c;也必须后来居上。 数科星球原创 作者丨苑晶 编辑丨大兔 从GPT3.5彻底出圈后&#xff0c;大模型的影响力开始蜚声国际。一段时间内&#xff0c;国内科技公司可谓被ChatGPT按在地上打&#xff0c;毫无还手之力。 彼时&#xff0c;很多企业…

echarts实现中国地图下钻进入下一级行政区(地图钻取)

获取geo数据&#xff1a; 可以使用node爬虫获取数据 最好多爬几遍&#xff0c;因为有时候会获取错误 echarts实现 html <div ref"echarts-dom" class"echarts-content"></div>js: export default {data() {return {mapChart: null,addressC…

太心累!企业IT维修呼唤更专业的维修平台

大数据产业创新服务媒体 ——聚焦数据 改变商业 设想这样一个场景&#xff1a;在繁忙的工作日早晨&#xff0c;企业的运营部门突然发现一批重要的办公设备&#xff0c;台式电脑、笔记本电脑和打印机&#xff0c;出现了各种技术问题。无法连接网络、电脑启动异常、软件冲突等问…

【SQL应知应会】索引(一)• MySQL版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 索引 • MySQL版 前言一、索引1.简介1.1 索引的优点…

业界首个云管理产品与服务图谱发布,九州未来入选!

近日&#xff0c;由中国信息通信研究院和中国通信标准化协会联合主办的第十届可信云大会在北京成功召开&#xff0c;会上发布业界首个云管理全景图《云管理产品与服务图谱&#xff08;2023&#xff09;》。 九州未来凭借在云管理领域的多年深耕&#xff0c;成功入选“智慧应用…

【数学建模学习(9):模拟退火算法】

模拟退火算法(Simulated Annealing, SA)的思想借 鉴于固体的退火原理&#xff0c;当固体的温度很高的时候&#xff0c;内能比 较大&#xff0c;固体的内部粒子处于快速无序运动&#xff0c;当温度慢慢降 低的过程中&#xff0c;固体的内能减小&#xff0c;粒子的慢慢趋于有序&a…

无涯教程-Perl - defined函数

描述 如果 EXPR 的值不是undef值,则此函数返回true&#xff1b;如果未指定 EXPR ,则检查$_的值。它可以与许多功能一起使用以检测操作失败,因为如果出现问题,它们将返回undef。简单的布尔测试不会区分false,零,空字符串或字符串.0。 如果 EXPR 是函数或函数引用,则在定义函数…

ORCA优化器浅析——CFunctionProp function properties

CFunctionProp CFunctionProp代表了function properties函数属性&#xff0c;主要由function stability函数易变性&#xff08; enum EFuncStbl { EfsImmutable, /* never changes for given input */ EfsStable, /* does not change within a scan */ EfsVolatile, /* can ch…

objectMapper.configure 方法的作用和使用

objectMapper.configure 方法是 Jackson 提供的一个用于配置 ObjectMapper 对象的方法。ObjectMapper 是 Jackson 库的核心类&#xff0c;用于将 Java 对象与 JSON 数据相互转换。 configure 方法的作用是设置 ObjectMapper 的配置选项&#xff0c;例如设置日期格式、设置序列…

Stephen Wolfram:超越基础训练

Beyond Basic Training 超越基础训练 The majority of the effort in training ChatGPT is spent “showing it” large amounts of existing text from the web, books, etc. But it turns out there’s another—apparently rather important—part too. 在训练 ChatGPT 的过…

基于短信宝API零代码实现短信自动化业务

场景描述&#xff1a; 基于短信宝开放的API能力&#xff0c;实现在特定事件&#xff08;如天气预警&#xff09;或定时自动发送短信&#xff08;本文以定时群发短信为例&#xff09;。通过Aboter平台如何实现呢&#xff1f; 使用方法&#xff1a; 首先创建一个IPaaS流程&…

splice没有删除指定元素怎么回事

动态删除数组元素&#xff0c;只能用倒序遍历或者正序遍历时i每次减1 防止遍历时数组元素长度动态改变导致的死循环或者缺漏 注释的需要-1

io day9

1&#xff0e;要求用消息队列实现AB进程对话 a.A进程先发送—句话给B进程&#xff0c;B进程接收后打印 b.B进程再回复—句话给A进程&#xff0c;A进程接收后打印 c.重复1.2步骤&#xff0c;当收到quit后&#xff0c;要结束AB进程 d.实现随时收发:用多进程多线程。 2.要求在共享…

NC 突破性发现!新型分子抑制细菌多重耐药性,重燃抗生素效力的希望

多重耐药性是指细菌病原体在许多结构多样化的化合物的致死剂量下存活的能力。细菌多重耐药性继续以惊人的速度蔓延&#xff0c;威胁着全球人类健康。2019年&#xff0c;细菌多重耐药性直接导致全球1万人死亡&#xff0c;超过艾滋病毒和疟疾的总和。 由于大多数临床抗生素已经对…

Docker卸载安装及国内镜像源(详细版)

文章目录 一、卸载已有Docker1、首先判断本地有没有docker&#xff1a;2、判断CentOS下 docker是否在运行&#xff1a;3、停止docker运行&查看状态4、yum查看docker安装的包并卸载5、删除docker安装目录6、查看docker version 二、Docker安装及镜像源配置1、centOS 7 yum源…

第7集丨Vue 江湖 —— 条件渲染

目录 一、v-show二、v-if2.1 基本使用2.2 条件渲染分组2.3 与 v-else-if、v-else 结合使用 三、v-if vs v-show四、测试案例 本节条件渲染所涉及到的指令有&#xff1a; v-showv-ifv-else-ifv-else 一、v-show 1. 用法&#xff1a; 语法: v-show" 表达式"&#xff…