当前位置: 首页 > news >正文

Java中的反射使用

1、获取Class对象的三种方式

1、对象调用Object类的getClass()方法(对象.getClass())

2、调用类的class属性(类名.class)

3、调用Class类的静态方法(Class.forName(“包名.类名”))常用

Student类

package com.example.reflection;public class Student {
}

测试类

public class Demo {public static void main(String[] args) {//对象调用父类Object的getClass()方法Student student = new Student();Class<? extends Student> clazz = student.getClass();System.out.println(clazz);//调用类的class属性Class<Student> stu = Student.class;System.out.println(stu);//调用Class类的静态方法forName()向方法中传一个字符串(包名.类名)try {Class<?> c = Class.forName("com.example.reflection.Student");System.out.println(c);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}
}

运行结果:
获取Class对象的三种方式

2、获取构造方法

1、getConstructors() 获取被public修饰构造方法

2、getDeclaredConstructors() 获取所有构造方法(包括:private、protected、默认、public)

3、getConstructor(参数类型…) 获取单个被public修饰构造方法 (参数类型为可变参数,有几个参数就写几个,值为null时,表示获取无参构造)

4、getDeclaredConstructor(参数类型…) 根据参数类型获取单个构造方法(包括:private、protected、默认、public),参数类型同getConstructor一样

5、setAccessible(true) Constructor对象调用该方法 暴力访问该方法,忽略掉所有访问修饰符

Student类

package com.example.reflection;public class Student {/*** 默认构造方法** @param str 形参*/Student(String str) {System.out.println("默认构造方法执行了...");}/*** 无参构造方法*/public Student() {System.out.println("无参构造方法执行了...");}/*** 一个参数的构造方法** @param age 年龄*/public Student(int age) {System.out.println("年龄:" + age);}/*** 多参构造方法** @param name     姓名* @param age      年龄* @param password 密码*/public Student(String name, int age, String password) {System.out.println("姓名:" + name + "年龄:" + age + "密码:" + password);}protected Student(boolean n) {System.out.println("受保护的构造方法执行了..." + n);}/*** 私有构造方法** @param sex 性别*/private Student(char sex) {System.out.println("私有构造方法执行了..." + sex);}
}

测试类

public class Demo {public static void main(String[] args) {try {//加载Class对象Class<?> clazz = Class.forName("com.example.reflection.Student");//获取所有公有构造方法Constructor<?>[] constructors = clazz.getConstructors();System.out.println("公有构造方法:");System.out.println(Arrays.toString(constructors));System.out.println("=======================");constructors = clazz.getDeclaredConstructors();System.out.println("所有构造方法(包括私有、受保护、默认和公有):");System.out.println(Arrays.toString(constructors));System.out.println("=======================");System.out.println("公有无参构造方法:");Constructor<?> con = clazz.getConstructor(null);System.out.println(con);System.out.println("=======================");con = clazz.getConstructor(int.class);System.out.println("公有有参构造方法:");System.out.println(con);System.out.println("=======================");con = clazz.getDeclaredConstructor(char.class);System.out.println("私有有参构造方法:");System.out.println(con);System.out.println("=======================");System.out.println("暴力访问(忽略掉访问修饰符):");Constructor<?> c = clazz.getDeclaredConstructor(char.class);c.setAccessible(true);c.newInstance('男');} catch (Exception e) {throw new RuntimeException(e);}}
}

运行结果:
获取构造方法

3、获取成员变量并调用

1、getFields() 获取所有被public修饰字段

2、getDeclaredFields() 获取所有字段(包括:private、protected、默认、public)

3、getField(字段名) 根据字段名获取被public修饰字段

4、getDeclaredField(字段名) 根据字段名获取字段(包括:private、protected、默认、public所修饰的字段)

Student

package com.example.reflection;public class Student {public int height;double weight;private String name;private int age;private char sex;private String password;/*** 无参构造方法*/public Student() {System.out.println("无参构造方法执行了...");}
}

测试类

public class Demo {public static void main(String[] args) {try {Class<?> clazz = Class.forName("com.example.reflection.Student");Field[] fields = clazz.getFields();System.out.println("获取所有公有的字段:");System.out.println(Arrays.toString(fields));System.out.println("=======================");fields = clazz.getDeclaredFields();System.out.println("获取所有字段(包括私有、受保护、默认和公有):");System.out.println(Arrays.toString(fields));System.out.println("=======================");System.out.println("获取公有的字段并赋值:");Field height = clazz.getField("height");System.out.println("身高:" + height);Object obj = clazz.getConstructor().newInstance();height.set(obj, 180);Student stu = (Student) obj;System.out.println("学生身高:" + stu.height + "cm");System.out.println("=======================");System.out.println("获取默认字段并赋值:");Field weight = clazz.getDeclaredField("weight");System.out.println("体重:" + weight);weight.set(obj, 82.5);System.out.println("学生体重:" + stu.weight + "kg");} catch (Exception e) {throw new RuntimeException(e);}}
}

运行结果:
获取成员变量

4、获取成员方法并调用

1、getMethods() 获取所有被public所修饰的成员方法

2、getDeclared() 获取所有成员方法(包括:private、protected、默认、public)

3、getMethod(方法名称,方法参数…) 根据方法名称、参数获取被public修饰的方法

4、getDeclaredMethod(方法名称,方法参数…) 根据方法名称、参数获取默认、被protected修饰的方法

5、Method中的invoke(对象,参数值…)可以执行方法,若要执行被private修饰的方法,需要设置Method对象.setAccessible(true)解除私有限定

Student

package com.example.reflection;public class Student {/*** 无参构造方法*/public Student() {System.out.println("无参构造方法执行了...");}public void test1(String str) {System.out.println("调用了公有的、String参数的方法" + str + "...");}protected void test2() {System.out.println("调用了受保护的、无参的方法test2...");}void test3() {System.out.println("调用了默认的、无参的方法test3...");}private static String test4(int age) {System.out.println("调用了私有的、有参、有返回值的方法test4..." + age);return "test4的返回值";}
}

测试类

public class Demo {public static void main(String[] args) {try {Class<?> clazz = Class.forName("com.example.reflection.Student");Method[] methods = clazz.getMethods();System.out.println("获取所有公有的成员方法:");System.out.println(Arrays.toString(methods));System.out.println("=======================");methods = clazz.getDeclaredMethods();System.out.println("获取所有成员方法(包括私有、受保护、默认和公有):");System.out.println(Arrays.toString(methods));System.out.println("=======================");Method test1 = clazz.getMethod("test1", String.class);System.out.println(test1);Object obj = clazz.getConstructor().newInstance();test1.invoke(obj, "test1");System.out.println("=======================");Method test3 = clazz.getDeclaredMethod("test3");System.out.println(test3);test3.invoke(obj);System.out.println("=======================");Method test4 = clazz.getDeclaredMethod("test4", int.class);System.out.println(test4);test4.setAccessible(true); //解除私有限定Object result = test4.invoke(obj, 15);System.out.println("返回值:" + result);} catch (Exception e) {throw new RuntimeException(e);}}
}

获取成员方法

5、获取main方法并执行

Student

package com.example.reflection;public class Student {public static void main(String[] args) {System.out.println("Student中的main方法执行了...");}
}

测试类

public class Demo {public static void main(String[] args) {try {//1、获取Student的字节码文件Class<?> clazz = Class.forName("com.example.reflection.Student");//2、获取main方法Method main = clazz.getMethod("main", String[].class);//3、调用main方法//      第一个参数:对象类型,因为方法时静态的,所有为null可以//      第二个参数:String数组,这里要注意在JDK1.4之后是数组,JDK1.5之后为可变参数//      这里拆的时候将new String[]{"a","b","c"}拆成3个对象所有需要强制转换main.invoke(null, (Object) new String[]{"a", "b", "c"});
//            main.invoke(null,new Object[]{new String[]{"a","b","c"}}); //这样也可以} catch (Exception e) {throw new RuntimeException(e);}}
}

运行结果:
获取main方法并执行

6、通过反射运行配置文件内容

​ 利用反射和配置文件,可以使应用程序更新时,对源码无需进行修改,只需将类发送给客户端,修改配置文件即可

application.properties

classname=com.example.reflection.Student
methodName=test3

Student

package com.example.reflection;public class Student {/*** 无参构造方法*/public Student() {System.out.println("无参构造方法执行了...");}public void test1(String str) {System.out.println("调用了公有的、String参数的方法" + str + "...");}
}

测试类

public class Demo {public static void main(String[] args) {Properties prop = new Properties();InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties");try {prop.load(is);//获取类String classname = prop.getProperty("classname");Class<?> clazz = Class.forName(classname);//获取方法名String methodName = prop.getProperty("methodName");Method test2 = clazz.getDeclaredMethod(methodName);test2.invoke(clazz.getConstructor().newInstance());} catch (Exception e) {throw new RuntimeException(e);}}
}

运行结果:
通过反射运行配置文件内容

7、通过反射越过泛型检查

需求:有一个List list,向其中添加Integer类型的数据

测试类

public class Demo {public static void main(String[] args){List<String> list = new ArrayList<>();list.add("aaa");list.add("bbb");//获取ArrayList的Class对象,反向调用add()方法Class<? extends List> clazz = list.getClass();try {Method add = clazz.getMethod("add", Object.class);add.invoke(list, 13);} catch (Exception e) {throw new RuntimeException(e);}for (Object obj : list) {System.out.println(obj);}}
}

运行结果:
通过反射越过泛型检查

相关文章:

Java中的反射使用

1、获取Class对象的三种方式 1、对象调用Object类的getClass()方法&#xff08;对象.getClass()&#xff09; 2、调用类的class属性&#xff08;类名.class&#xff09; 3、调用Class类的静态方法&#xff08;Class.forName(“包名.类名”)&#xff09;常用 Student类 package…...

urho3d工具

AssetImporter 加载开放资源导入库支持的各种三维格式(http://assimp.sourceforge.net/)并保存Urho3D模型、动画、材质和场景文件。有关支持的格式列表&#xff0c;请参阅http://assimp.sourceforge.net/main_features_formats.html. Blender的另一种导出路径是使用Urho3D插件…...

HashMap数据结构

HashMap概述 HashMap是基于哈希表的Map接口实现的&#xff0c;它存储的是内容是键值对<key,value>映射。此类不保证映 射的顺序&#xff0c;假定哈希函数将元素适当的分布在各桶之间&#xff0c;可为基本操作(get和put)提供稳定的性能。 HashMap在JDK1.8以前数据结构和存…...

BFC的含义以及应用

什么是BFC? BFC全称是Block Formatting context&#xff0c;翻译过来就是块级格式化上下文。简单来说&#xff0c;BFC是一个完全独立的空间。让空间里的子元素不会影响到外面的布局。&#x1f603;&#x1f603;&#x1f603; 如何触发BFC呢&#xff1f; mdn给了如下方式&a…...

电脑技巧:分享8个Win11系统必备小技巧

目录 1、让任务栏显示“右键菜单” 2、任务栏置顶 3、还原经典右键菜单 4、Win11版任务管理器 5、新版AltTab 6、开始菜单不再卡 7、为Edge浏览器添加云母效果 8、自动切换日/夜模式 Win11在很多地方都做了调整&#xff0c;但由于涉及到诸多旧有习惯&#xff0c;再加上…...

C/C++每日一练(20230226)

目录 17. 电话号码的字母组合 37. 解数独 51. N 皇后 52. N皇后 II 89. 格雷编码 90. 子集 II 17. 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电…...

Vue 3第二章:Vite文件目录结构及SFC语法

文章目录1. Vite 文件目录结构2. Vue3 SFC 语法规范介绍1. Vite 文件目录结构 Vue3 并没有强制规定文件目录结构&#xff0c;开发者可以按照自己喜欢的方式组织代码。不过&#xff0c;通常情况下&#xff0c;我们会按照以下方式组织文件目录&#xff1a; ├── public │ …...

Leetcode 剑指 Offer II 016. 不含重复字符的最长子字符串

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的最长…...

TCP 的演化史-sack 与 reordering metric

就着 TCP 本身说事&#xff0c;而不是高谈阔论关于它是如何不合时宜&#xff0c;然后摆出一个更务虚的更新。 从一个 case 开始。 按照现在 Linux TCP(遵守 RFC) 实现&#xff0c;以下是一个将会导致 reordering 更新的 sack 序列&#xff1a; 考虑一种情况&#xff0c;这两个…...

【Spring6】| Spring的入门程序、集成Log4j2日志框架

目录 一&#xff1a;Spring的入门程序 1. Spring的下载 2. Spring的jar文件 3. 第一个Spring程序 4. 第一个Spring程序详细剖析 5. Spring6启用Log4j2日志框架 一&#xff1a;Spring的入门程序 1. Spring的下载 官网地址&#xff1a;https://spring.io/ 官网地址&…...

包子凑数(完全背包)

小明几乎每天早晨都会在一家包子铺吃早餐。 他发现这家包子铺有 N 种蒸笼&#xff0c;其中第 i种蒸笼恰好能放 Ai 个包子。 每种蒸笼都有非常多笼&#xff0c;可以认为是无限笼。 每当有顾客想买 X 个包子&#xff0c;卖包子的大叔就会迅速选出若干笼包子来&#xff0c;使得这若…...

Spring超级全家桶,学完绝对是惊艳面试官的程度

前言Spring框架自2002年诞生以来一直备受开发者青睐&#xff0c;它包括SpringMVC、SpringBoot、Spring Cloud、Spring Cloud Dataflow等解决方案。有人亲切的称之为&#xff1a;Spring 全家桶。很多研发人员把spring看作心目中最好的java项目&#xff0c;没有之一。所以这是重点…...

Redis主要数据类型

Redis 是一个数据结构服务器。 Redis 的核心是提供一系列本机数据类型&#xff0c;可帮助您解决从缓存到队列再到事件处理的各种问题Redis主要数据类型&#xff1a;String&#xff08;字符串&#xff09;&#xff0c;Lists&#xff08;列表&#xff09;&#xff0c;Sets&#x…...

【Linux | ELK 8.2】搭建ELKB集群Ⅰ—— 实验环境说明和搭建Elasticsearch集群

目录1. 实验环境1.1 实验工具1.2 操作系统1.3 架构版本、IP地址规划与虚拟机配置要求1.4 拓扑图1.5 其他要求2. 实验步骤2.1 安装Elasticsearch&#xff08;单节点&#xff09;&#xff08;1&#xff09;检查系统jdk版本&#xff08;2&#xff09;下载elasticsearch&#xff08…...

不同情况下*p和*p的区别(指针)

一说到指针&#xff0c;不少同学就会觉得云里雾里。首先要明白&#xff0c;指针和地址是一个概念&#xff1b;然后明白指针和指针变量的区别。先理解地址和数据&#xff0c;想象内存里面是一个个的小盒子&#xff0c;每个盒子对应一个编号&#xff0c;这个编号就是地址&#xf…...

Vuex基础语法

Vuex vuex官网 文章目录Vuexvuex的工作原理图2.vuex的环境搭建3.vuex的使用1.actons2. mutations3.getters4.vuex中的map映射属性4.1 mapState和mapGetters4.2 mapMutations和mapActions5.vuex多组件通信1.通过计算属性获得2.通过mapState获得6.vuex模块化和命名空间6.1模块化…...

刚上岸字节测试开发岗,全网最真实的大厂面试真题

首先我来解释一下为什么说是全网最真实的面试题&#xff0c;相信大家也发现软件测试面试题在网上流传也已不少&#xff0c;但是经过仔细查看发现了两个很重要的问题。 第一&#xff0c;网上流传的面试题的答案并不能保证百分百正确。也就是说各位朋友辛辛苦苦花了很多时间准备…...

Mac监控键盘输入并执行动作

最新内容在我的另一个博客&#xff1a;Mac监控键盘输入并执行动作 背景 电脑的安全是非常重要的&#xff0c;特别是里面的敏感数据&#xff0c;若是被有心之人利用&#xff0c;那后果不堪设想。 所以我们部门定下了一个规矩&#xff0c;谁离开工位要是不锁屏&#xff0c;就可以…...

Transformer输出张量的值全部相同?!

Transformer输出张量的值全部相同&#xff1f;&#xff01;现象原因解决现象 输入经过TransformerEncoderLayer之后&#xff0c;基本所有输出都相同了。 核心代码如下&#xff0c; from torch.nn import TransformerEncoderLayer self.trans TransformerEncoderLayer(d_mode…...

港科夜闻|全国政协副主席梁振英先生率香港媒体高管团到访香港科大(广州)...

关注并星标每周阅读港科夜闻建立新视野 开启新思维1、全国政协副主席梁振英先生率香港媒体高管团到访香港科大(广州)。2月21日下午&#xff0c;在全国政协副主席、广州南沙粤港合作咨询委员会顾问梁振英先生的带领下&#xff0c;香港20余家媒体的高管及知名媒体人士到访香港科大…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...