Java 注解与反射(超详细!!!)

article/2025/8/20 9:05:01

Java 注解与反射(超详细!!!)

文章目录

  • Java 注解与反射(超详细!!!)
    • 1.注解
      • 1.1内置注解
        • 1.1.1 @SuppressWarnings注解用法
      • 1.2 元注解
      • 1.3自定义注解
    • 2.反射
      • 2.1 反射的用途
      • 2.2 反射的使用方法
      • 2.3 class类型的对象使用场景1:
      • 2.4 class类型的对象使用场景2:
      • 2.5 通过反射创造对象
      • 2.6 使用反射机制获取和调用类的构造方法,访问私有构造方法并创建对象
      • 2.7 通过反射,访问并使用成员方法

1.注解

1.1内置注解

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

例如:

@override:定义在java.lang.override 中,此注释只适用于修辞方法,表示一个方法声明打算
重写超类中的另一个方法声明

@Deprecated:定义在java.lang.Deprecated中,此注释可以用于修辞方法,属性,类,表示不
鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择

@SuppressWarnings:定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息.与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好了的,我们选择性的使用就好了

例如

@SuppressWarnings("all")@SuppressWarnings("unchecked")@SuppressWarnings(value={unchecked", "deprecation")
、、、

接下来,我们通过一个案例,讲解一下注解是如何使用的,该如何使用。

//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.public class Main implements Sum {public static void main(String[] args) {Main m = new Main();m.sum();m.sum1();}@Deprecated //  不建议使用的注解public void sum1() {System.out.println("nihao11111");}@Overridepublic void sum() {System.out.println("nihao");}}

在此案例中,我们通过了@Deprecated 表明这个一个不建议使用的方法。但是,这仅仅是建议,我们仍然可以使用。

1.1.1 @SuppressWarnings注解用法

@SuppressWarnings 批注允许您选择性地取消特定代码段(即,类或方法)中的警告。其中的想法是当您看到警告时,您将调查它,如果您确定它不是问题,

就可以添加一个 @SuppressWarnings 批注,以使您不会再看到警告。虽然它听起来似乎会屏蔽潜在的错误,但实际上它将提高代码安全性,因为它将防止您对警告无动于衷 — 您看到的每一个警告都将值得注意。

例如下面这个例子,idea会爆一个警告,上述代码编译通过且可以运行,但每行前面的“感叹号”就严重阻碍了我们判断该行是否设置的断点了。这时我们可以在方法前添加@SuppressWarnings(“unused”) 去除这些“感叹号”。

Contents of collection 'items' are updated, but never queried
package 蓝桥杯国赛刷题;import java.util.ArrayList;
import java.util.List;public class commentTest01 {public static void main(String[] args) {commentTest01 CommentTest01 = new commentTest01();CommentTest01.addItems("1234");}public void addItems(String item) {List items = new ArrayList();items.add(item);}
}

1.2 元注解

元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明.

这些类型和它们所支持的类在java.lang.annotation包中可以找到分别是@Target, @Retention ,@Documented , @lnherited

@Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
@Retention :表示需要在什么级别保存该注释信息,用于描述注解的生命周期
@Document:说明该注解将被包含在javadoc中
@lnherited:说明子类可以继承父类中的该注解

1.3自定义注解

我们根据先前的注解写法,模仿自己写一个注解

在这里插入图片描述

通过观察创造注解包含以下元素@interface ,@Documented,@Retention,Target使用 @interface自定义注解时,自动继承了java.lang.annotation.Annotation接口

@ intertace用来声明一个注解,格式:public @ intertace 注解名{定义内容}

其中的每一个方法实际上是声明了一个参数,方法的名称就是参数的名称返回值类型就是参数的类型( 返回值只能是基本类型,Class, String, enum )。可以通过default来声明参数的默认值。如果只有一个参数成员,一般参数名为value。注解元素必须要有值,我们定义注解元素时,经常使用空字符串,O作为默认值。

自定义注解样例:

//自定义注解
public class test03 {//注解可以显示赋值, 如果没有默认值,我们就必须给注解赋值//注解参数的顺序随意@MyAnnotation2(age = 18, name = "jacky")public void test() {}@MyAnnotation3("jacky")public void test2() {}
}@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{//注解的参数: 参数类型 + 参数名 + ();String name() default "";int age() default 0;int id() default -1;String[] schools() default {"peking university"};
}@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{//如果注解参数为value赋值时可以直接写值String value();
}

在这个例子我们,我们定义了两个注解,分别是@MyAnnotation2,@MyAnnotation3,其参数不相同。

2.反射

反射(Reflection)是一种 Java 程序运行期间动态技术,可以在运行时(runtime)检査、修改其自身结构或行为。通过反射,程序可以访问、检测和修改它自己的类、对象、方法、属性等成员

在连接数据库中,反射的作用在于使用其特殊机制,直接调用目标类的构造方法。类如这段代码中

Class.forName("com.mysql.jdbc.Driver");

通过反射的机制,将 com.mysql.jdbc.Driver 这个类加载到 JVM 中。触发静态初始化块:MySQL 的驱动类在静态初始化块中会执行 DriverManager.registerDriver(new Driver()),自动向 DriverManager 注册自己,使得后续可以通过 DriverManager.getConnection()建立数据库连接。

2.1 反射的用途

  • 动态加载类:程序可以在运行时动态地加载类库中的类;
  • 动态创建对象:反射可以基于类的信息,程序可以在运行时,动态创建对象实例;
  • 调用方法:反射可以根据方法名称,程序可以在运行时,动态地调用对象的方法(即使方法在编写程序时还没有定义)
  • 访问成员变量:反射可以根据成员变量名称,程序可以在运行时,访问和修改成员变量(反射可以访问私有成员变量)
  • 运行时类型信息:反射允许程序在运行时,查询对象的类型信息,这对于编写通用的代码和库非常有用;

​ Spring 框架使用反射来自动装配组件,实现依赖注入;

​ MyBatis 框架使用反射来创建resultType 对象,封装数据查询结果;

2.2 反射的使用方法

反射的第一步是获取 Class 对象。Class 对象表示某个类的元数据,可以通过以下几种方式获取:

//获取Class类型信息
public class Text02 {public static void main(String[] args) throws ClassNotFoundException {//方式1:通过类名Class stringClass1 = String.class;//方式2:通过Class类的forName()方法Class stringClass2 = Class.forName("java.lang.String");//方式3:通过对象调用getClass()方法Class stringClass3 = "".getClass();System.out.println(stringClass1.hashCode());//1604839423System.out.println(stringClass2.hashCode());//1604839423System.out.println(stringClass3.hashCode());//1604839423}}

2.3 class类型的对象使用场景1:

//Class类型的对象使用场景1
public class Text03 {public static void main(String[] args) {String json= "{\"name\":\"长安荔枝\",\"favCount\":234}";         Document doc=JSON.parseObject(json,Document.class);System.out.println(doc.getName());System.out.println(doc.getFavCount());}}

使用 JSON.parseObject 方法将 JSON 字符串解析为 Document 类的对象。在解析过程中,JSON 字符串中的数据会自动映射到 Document 类的对应字段中。

2.4 class类型的对象使用场景2:

通过 Class 对象在运行时获取一个类的相关信息,包括类名、包名、成员变量(字段)、成员方法等。

//Class类型的对象使用场景2
//获取丰富的类型内容
public class Text04 {public static void main(String[] args) throws ClassNotFoundException {Class clz = Class.forName("java.util.HashMap");//获取类名System.out.println("完全限定名:"+clz.getName());System.out.println("简单的类名:"+clz.getSimpleName());//获取包名System.out.println("package"+clz.getPackage().getName());System.out.println();//获取成员变量Field[] fieldArray =clz.getDeclaredFields();System.out.println("成员变量(字段)");for(Field field:fieldArray) {System.out.println(field);}System.out.println();//获取成员方法Method[] methodArray = clz.getDeclaredMethods();System.out.println("成员方法");for(Method method:methodArray) {System.out.println(method);}	}
}
  • clz.getName() 返回类的完全限定名,包括包名,例如 "java.util.HashMap"
  • clz.getSimpleName() 返回类的简单名称,不包括包名,例如 "HashMap"
  • clz.getPackage().getName() 返回类所属的包名,例如 "java.util"
  • clz.getDeclaredFields() 返回一个 Field 数组,包含了类声明的所有字段(包括私有字段)。
  • clz.getDeclaredMethods() 返回一个 Method 数组,包含了类声明的所有方法(包括私有方法)。

2.5 通过反射创造对象

有两种方式通过反射创造对象分别是:

方式一:通过 Class 对象直接调用 newInstance() 方法

方式二:通过获取构造方法(Constructor)来创建对象。

//通过反射的方式,创建对象
public class Text05 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {Class clz = Class.forName("com.apesource.demo01.Document");//方式1:直接通过Class对象,调用newInstance()方法Object objx = clz.newInstance();//相当于在执行无参构造方法//方式2:通过构造器(构造方法)//无参构造方法Constructor constructor1 = clz.getDeclaredConstructor();//获取无参构造方法System.out.println(constructor1);Object obj1 = constructor1.newInstance();//执行构造器(构造方法),创建对象//有参构造方法Constructor constructor2 = clz.getDeclaredConstructor(String.class);//获取有参构造方法System.out.println(constructor2);Object obj2 = constructor2.newInstance("两京十五日");Constructor constructor3 = clz.getDeclaredConstructor(int.class);//获取有参构造方法System.out.println(constructor3);Object obj3 = constructor3.newInstance(34);Constructor constructor4 = clz.getDeclaredConstructor(String.class,int.class);//获取有参构造方法System.out.println(constructor4);Object obj4 = constructor4.newInstance("风起陇西",64);System.out.println(objx);System.out.println(obj1);System.out.println(obj2);System.out.println(obj3);System.out.println(obj4);}
  • newInstance() 方法是 Class 对象提供的一个方法,它调用类的无参构造方法来创建类的实例。
  • 注意:这个方法在 Java 9 以后已经被弃用,推荐使用 Constructor 对象来创建实例。
  • 通过 getDeclaredConstructor() 方法获取 Document 类的无参构造方法,然后调用 newInstance() 方法创建实例。
  • 注意:如果类中没有无参构造方法,调用 getDeclaredConstructor() 会抛出 NoSuchMethodException
  • 通过 getDeclaredConstructor(String.class) 获取带有一个 String 参数的构造方法,并传入 "两京十五日" 作为参数来创建对象。
  • 通过 getDeclaredConstructor(int.class) 获取带有一个 int 参数的构造方法,并传入 34 作为参数来创建对象。

2.6 使用反射机制获取和调用类的构造方法,访问私有构造方法并创建对象

public class Text06 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {Class clz = Class.forName("com.apesource.demo01.Document");//获取一组构造器Constructor[] constructorArray1 = clz.getConstructors();//publicConstructor[] constructorArray2 = clz.getDeclaredConstructors();//public、private//获取指定构造器Constructor constructor1 = clz.getConstructor();Constructor constructor2 = clz.getDeclaredConstructor(String.class);System.out.println(constructor1);System.out.println(constructor2);//调用私有构造器,必须设置它的访问全限constructor2.setAccessible(true);//调用构造器,创建对象Object obj = constructor2.newInstance("长安三万里");System.out.println(obj);}}
  • getConstructors() 方法返回一个包含所有公共(public)构造方法的数组。如果类中没有 public 构造方法,则返回空数组。
  • getDeclaredConstructors() 方法返回一个包含所有声明的构造方法的数组(包括私有的、受保护的和默认访问级别的构造方法)。
  • getConstructor() 方法用于获取类的无参构造方法(必须是 public 的)。如果没有无参构造方法或者不是 public,则抛出 NoSuchMethodException
  • getDeclaredConstructor(Class<?>... parameterTypes) 方法用于获取指定参数类型的构造方法。这里通过传入 String.class 参数获取一个带有 String 参数的构造方法。这个构造方法可以是任何访问级别(publicprivateprotected、默认)。
  • setAccessible(true) 用于绕过 Java 访问控制机制,使私有构造方法也可以被调用。如果不设置 Accessibletrue,那么调用私有构造方法时会抛出 IllegalAccessException
  • newInstance(Object... initargs) 方法使用指定的构造方法创建对象。这里调用了带有 String 参数的构造方法,并传入 "长安三万里" 作为参数。

2.7 通过反射,访问并使用成员方法

public class Text08 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {//硬编码的方式
//		Document doc1 = new Document();
//		doc1.setName("海底两万里");
//		doc1.setFavCount(10025);//反射的方式Class clz = Class.forName("com.apesource.demo01.Document");//获取类型信息Object doc1 = clz.newInstance();//创建对象//获取指定名称和参数类型的方法Method setNameMethod = clz.getMethod("setName", String.class);Method setFavCountMethod = clz.getMethod("setFavCount", int.class);//执行方法//doc1.setName("海底两万里");setNameMethod.invoke(doc1, "海底两万里");//doc1.setFavCount(10025);setFavCountMethod.invoke(doc1, 10025);System.out.println(doc1);}}
  • getMethod(String name, Class<?>... parameterTypes) 方法用于获取类的某个 public 方法。方法名称和参数类型必须匹配才能成功获取方法。
  • invoke(Object obj, Object... args) 方法用于调用指定的实例方法。
  • setNameMethod.invoke(doc1, "海底两万里"); 等同于 doc1.setName("海底两万里");
  • setFavCountMethod.invoke(doc1, 10025); 等同于 doc1.setFavCount(10025);

以上便是Java注解与反射的全部内容了,笔者编写不易,恳请点赞收藏,欢迎评论区交流!!!


http://www.hkcw.cn/article/CtLlAuKuwj.shtml

相关文章

开关电源输出噪声--陶瓷 电解电容差异

对于LED恒流源驱动&#xff0c;输出只用电解电容&#xff0c;噪声大 对于LED恒流源驱动&#xff0c;输出用电解电容和陶瓷电容&#xff08;C77& C78改成22uf陶瓷电容&#xff09;&#xff0c;噪声小到50 mV左右

【运维实战】定时任务-crontab命令

定时任务的应用场景 数据备份 定期对重要数据进行备份&#xff0c;是保障数据安全的重要手段。比如&#xff0c;我们可以设置每周日凌晨对整个数据库进行全量备份&#xff0c;或者每天对关键业务数据进行增量备份。这样&#xff0c;即便遇到硬件故障、误操作等意外情况&#…

[免费]SpringBoot+Vue垃圾分类管理【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue垃圾分类管理【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】SpringbootVue垃圾分类管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 本论文主要论述了如何使用JAVA语言…

等保测评-Linux主机测评篇

Linux主机测评 目录 Linux主机测评 0x01 前言 0x02 测评过程 1.身份的鉴别 a).对登陆的用户进行身份鉴别和标识&#xff0c;身份标识具有唯一性 b).应具有登录次数限制&#xff0c;登陆超时等措施 c).在进行远程控制中&#xff0c;防止传输过程被窃听 2.访问控制 a).…

面向对象基本概念:多态;附带应用例子

目录 一. 多态的概念简介 二. 多态的例子一&#xff1a;偏好过滤器 三. 多态的例子二&#xff1a;审查描述符(需要元编程知识) 四. 总结 面向对象编程(Object Oriented Programming&#xff0c;OOP)有三大核心概念&#xff1a;封装&#xff0c;继承&#xff0c;多态。前两个…

Linux 串口连接乱码

用到的全部软件&#xff0c;都放在这个网盘里面了&#xff0c;自取。 链接: https://pan.baidu.com/s/1AR6Lj8FS7bokMR5IrLmsIw?pwd3dzv 提取码: 3dzv 如果链接失效了&#xff0c;关注公号&#xff1a;每日早参&#xff0c;回复&#xff1a;资源&#xff0c;即可免费获取&…

linux之web实战rsync

一、rsync简介 rsync是用于数据备份共享以及增量同步的工具&#xff0c;它可以在本地计算机与远程计算机之间&#xff0c;或者两个本地目录之间同步文件&#xff08;但不支持两台远程计算机之间的同步&#xff09;。它也可以当作文件复制工具&#xff0c;替代cp和mv命令 二、…

链表经典题目(力扣 easy)

全部题目来自力扣&#xff0c;这里只做学习的记录&#xff0c;内容中部分为AI生成&#xff0c;有不对的地方可以评论或者私信哦~~ 203. 移除链表元素 &#xff08;版本一&#xff09;虚拟头节点法 # Definition for singly-linked list. # class ListNode: # def __init_…

UFSH2024 程序化生成 笔记

这篇只是把里面涉及到的网站连接做个记录。有些网站“藏"得太深了。找了半天才找到相关连接 官方视频&#xff1a; [UFSH2024]关于程序化生成&#xff0c;我们还能做什么&#xff1f; | 周杰 徐凯鸣 腾讯IEG Global_哔哩哔哩_bilibili 官方案例资源连接&#xff1a; Vit…

openEuler安装MySql8(tar包模式)

操作系统版本&#xff1a; openEuler release 22.03 (LTS-SP4) MySql版本&#xff1a; 下载地址&#xff1a; https://dev.mysql.com/downloads/mysql/ 准备安装&#xff1a; 上传安装包&#xff1a; 把下载下来的安装包上传到服务器&#xff1a;/opt/software/mysql目录…

JSON Schema

1.JSON Schema的含义 JSON Schema 是用于验证 JSON 数据结构的强大工具&#xff0c;Schema可以理解为模式或者规则&#xff0c;可以理解为JSON中的正则表达式 2.语法 2.1 type 作用&#xff1a;约束数据类型 取值范围&#xff1a;integer&#xff0c;string&#xff0c;object&…

替代 WPS 的新思路?快速将 Word 转为图片 PDF

在这个数字化办公日益普及的时代&#xff0c;越来越多的人开始关注文档处理工具的功能与体验。当我们习惯了某些便捷操作时&#xff0c;却发现一些常用功能正逐渐变为付费项目——比如 WPS 中的一项实用功能也开始收费了。 这款工具最特别的地方在于&#xff0c;可以直接把 W…

华为OD机试真题——Boss的收入(分销网络提成计算)(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…

中国批准修建最昂贵运河为何受关注 重塑交通格局引发国际热议

中国即将启动一项震惊全球的大工程——浙赣粤运河。该项目总投资3200亿元,刷新了中国运河造价纪录。这条运河北起浙江杭州,穿过江西,南至广东广州的珠江出海口,全长1237公里,其中江西境内占759公里。通过钱塘江、兰江等水系连接杭州,形成贯穿浙赣粤三省的水上通道。从交通…

广东河源24小时内连震两次 市民难眠

广东河源24小时内连震两次 市民难眠!中国地震台网正式测定,5月30日2时21分在广东河源市源城区发生3.0级地震,震源深度10公里,震中位于北纬23.72度,东经114.68度。此次地震震中5公里范围内平均海拔约52米。震中周边200公里内近5年来共发生3.0级以上地震15次,最大地震是202…

74.用户编辑功能在多次修复后仍未成功实现

在用户编辑功能在多次修复后仍未成功实现之后决定换种方法 对于后端则不需要过多修改&#xff0c;只需要修改前端即可 首先&#xff0c;在 data() 中添加新的状态&#xff1a; 用户模板部分可继续沿用之前的方法所留下来的代码 修改start、cancel、save方法 修改现有的 rege…

Void:免费且隐私友好的 AI 编码利器,挑战 Cursor 地位?

开发者圈儿里最近有点小激动&#xff0c;大家都在议论一个叫Void的开源AI代码编辑器。这家伙在GitHub上人气飙涨&#xff0c;短时间内就斩获了超过22.1k的星标&#xff0c;简直成了科技圈的新宠。它被誉为“黑马”&#xff0c;不仅因为它继承了大家都很熟悉的Visual Studio Cod…

Cadence Innvous导出GDS没有STDCELL/IO/NET/VIA问题的解决方法

Cadence Innvous导出GDS之后&#xff0c;可以重新导入Cadence Virtuoso进行查看。 1. Innovus设计完成后的GDS导出命令 导出gds命令&#xff1a; streamOut [-help] <fileName> [-attachNetProp <string>] [-dieAreaAsBoundary] [-libName <string>] [-map…

菲总统任命新国家警察总长 曾主导前总统逮捕行动

菲律宾总统马科斯选定国家警察刑事调查组组长尼古拉斯托雷出任国家警察新任总长。托雷此前主导了逮捕前总统杜特尔特的行动。菲总统执行秘书卢卡斯贝尔萨敏在马拉卡南宫记者会上宣布了这一任命。交接仪式定于6月2日举行,托雷将接替即将退休的现任总长罗梅尔马比尔。托雷成为马…

《深度搜索-R1-0528》

深度搜索-R1-0528 Paper Link &#xff08;纸质链接&#xff09;&#x1f441;️ 1. 引言 DeepSeek R1 模型进行了小版本升级&#xff0c;当前版本为 DeepSeek-R1-0528。在最新的更新中&#xff0c;DeepSeek R1 通过利用增加的计算资源并在后训练期间引入算法优化机制&#x…