Java基础——反射

1 概述

Java反射提供了一种动态获取类信息及动态修改运行规则的机制。
反射指运行时获取一个类中的信息,并控制其行为。运行时可以获取构造器对象Constructor,可以获取成员变量对象Field,可以获取方法对象Method

2 获取类对象的方式

获取Class对象有三种方式

public class Test {public static void main(String[] args) throws ClassNotFoundException {// Class类中的一个静态方法forNameClass clazz1 = Class.forName("com.xy.day01.Student");System.out.println(clazz1);// 通过类名.classClass clazz2 = Student.class;System.out.println(clazz2);// 通过对象的getClass方法Student student = new Student();Class clazz3 = student.getClass();System.out.println(clazz3);}
}

输出

class com.xy.day01.Student
class com.xy.day01.Student
class com.xy.day01.Student

Class对象是对象加载之后自动创建的一个对象,在堆中。每个类加载后,虚拟机都会为其创建一个对象在堆中,有且只有一个。

2 反射构造方法

涉及到的api

1. Constructor getConstructor(Class... parameterTypes)根据参数匹配获取某个构造器,只能拿public修饰的构造器,几乎不用!
2. Constructor getDeclaredConstructor(Class... parameterTypes)根据参数匹配获取某个构造器,只要申明就可以定位,不关心权限修饰符,建议使用!
3. Constructor[] getConstructors()获取所有的构造器,只能拿public修饰的构造器。几乎不用!!太弱了!
4. Constructor[] getDeclaredConstructors()获取所有申明的构造器,只要你写我就能拿到,无所谓权限。建议使用!!

测试类

public class Student {int age;String name;private Student() {System.out.println("无参构造执行了");}public Student(int age, String name) {System.out.println("有参构造执行了");this.age = age;this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student{" +"age=" + age +", name='" + name + '\'' +'}';}
}

2.1 获取所有public构造器

@Test
public void getConstructors() {Class<Student> clazz = Student.class;Constructor[] constructors = clazz.getConstructors();for (Constructor constructor : constructors) {System.out.println(constructor.getName() + " ===> " + constructor.getParameterCount());}
}

输出

com.xy.day02.Student ===> 2

该方法只能获取所有的public类型的构造器

2.2 获取所有构造器

@Test
public void getDeclaredConstructors() {Class<Student> clazz = Student.class;Constructor[] constructors = clazz.getDeclaredConstructors();for (Constructor constructor : constructors) {System.out.println(constructor.getName() + " ===> " + constructor.getParameterCount());}
}

输出

com.xy.day02.Student ===> 0
com.xy.day02.Student ===> 2

该方法能够获取所有的构造器,包括private类型的构造器

2.3 获取单个public构造器

@Test
public void getConstructor() throws NoSuchMethodException {Class<Student> clazz = Student.class;Constructor constructor = clazz.getConstructor();// Constructor<Student> constructor = clazz.getConstructor(int.class, String.class);System.out.println(constructor.getName() + " ===> " + constructor.getParameterCount());
}

报异常
在这里插入图片描述
因为无参构造是private的,该方法只能获取public类型的构造器,由于获取不到对应构造器,所以报异常。

@Test
public void getConstructor() throws NoSuchMethodException {Class<Student> clazz = Student.class;Constructor constructor = clazz.getConstructor();// Constructor<Student> constructor = clazz.getConstructor(int.class, String.class);System.out.println(constructor.getName() + " ===> " + constructor.getParameterCount());
}

输出

com.xy.day02.Student ===> 2

通过传入特定的class对象来获取对应的构造器

2.4 获取单个构造器

@Test
public void getDeclaredConstructor() throws NoSuchMethodException {Class<Student> clazz = Student.class;Constructor<Student> constructor1 = clazz.getDeclaredConstructor();Constructor<Student> constructor2 = clazz.getDeclaredConstructor(int.class, String.class);System.out.println(constructor1.getName() + " ===> " + constructor1.getParameterCount());System.out.println(constructor2.getName() + " ===> " + constructor2.getParameterCount());
}

输出

com.xy.day02.Student ===> 0
com.xy.day02.Student ===> 2

通过该方法可以获取包括private类型的构造器。

3 构造器的使用

@Test
public void useConstructor() throws Exception {Class<Student> clazz = Student.class;Constructor<Student> constructor = clazz.getDeclaredConstructor();System.out.println(constructor.getName() + " ===> " + constructor.getParameterCount());Student s = (Student) constructor.newInstance();System.out.println(s);
}

反射无参构造器,并创建对象,报异常
在这里插入图片描述
由于无参构造方法是private的,所以会报异常
可以通过setAccessible方法设置。

@Test
public void useConstructor() throws Exception {Class<Student> clazz = Student.class;Constructor<Student> constructor = clazz.getDeclaredConstructor();System.out.println(constructor.getName() + " ===> " + constructor.getParameterCount());constructor.setAccessible(true);Student s = (Student) constructor.newInstance();System.out.println(s);
}

输出

com.xy.day02.Student ===> 0
无参构造执行了
Student{age=0, name='null'}

setAccessible设置为true,表示可以暴力进入,无视权限控制。false为默认,保留权限控制。

@Test
public void useConstructor() throws Exception {Class<Student> clazz = Student.class;Constructor<Student> constructor = clazz.getDeclaredConstructor(int.class, String.class);System.out.println(constructor.getName() + " ===> " + constructor.getParameterCount());Student s = (Student) constructor.newInstance(12, "Bob");System.out.println(s);
}

输出

com.xy.day02.Student ===> 2
有参构造执行了
Student{age=12, name='Bob'}

4 反射字段

反射字段相关的api

1Field getField(String name);根据成员变量名获得对应Field对象,只能获得public修饰
2.Field getDeclaredField(String name);根据成员变量名获得对应Field对象,只要申明了就可以得到
3.Field[] getFields();获得所有的成员变量对应的Field对象,只能获得public4.Field[] getDeclaredFields();获得所有的成员变量对应的Field对象,只要申明了就可以得到

4.1 获取所有public字段

@Test
public void getFields() {Class clazz = Student.class;Field[] fields = clazz.getFields();for (Field field : fields) {System.out.println(field.getName() + "===>" + field.getType());}
}

返回为空,因为所有字段都是default的

4.2 获取所有字段

@Test
public void getDeclaredFields() {Class clazz = Student.class;Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {System.out.println(field.getName() + "===>" + field.getType());}
}

输出

age===>int
name===>class java.lang.String

4.3 获取单个public字段

@Test
public void getField() throws NoSuchFieldException {Class clazz = Student.class;Field field = clazz.getField("age");System.out.println(field.getName() + "===>" + field.getType());
}

抛异常,因为该字段不是public的
在这里插入图片描述

4.4 获取单个字段

@Test
public void getDeclaredField() throws NoSuchFieldException {Class clazz = Student.class;Field field = clazz.getDeclaredField("age");System.out.println(field.getName() + "===>" + field.getType());
}

输出

age===>int

5 字段的操作

常用api有

void set(Object obj, Object value):给对象注入某个成员变量数据
Object get(Object obj):获取对象的成员变量的值。
void setAccessible(true);暴力反射,设置为可以直接访问私有类型的属性。
Class getType(); 获取属性的类型,返回Class对象。
String getName(); 获取属性的名称。

代码示例:

@Test
public void useField() throws Exception {Class clazz = Student.class;Field field = clazz.getDeclaredField("age");Constructor<Student> constructor = clazz.getDeclaredConstructor();constructor.setAccessible(true);field.setAccessible(true);Student s = (Student) constructor.newInstance();field.set(s, 23);System.out.println(s);int age = (int) field.get(s);System.out.println(age);
}

输出

无参构造执行了
Student{age=23, name='null'}
23

6 反射方法

常用api

1Method getMethod(String name,Class...args);根据方法名和参数类型获得对应的方法对象,只能获得public2Method getDeclaredMethod(String name,Class...args);根据方法名和参数类型获得对应的方法对象,包括private3Method[] getMethods();获得类中的所有成员方法对象,返回数组,只能获得public修饰的且包含父类的
4Method[] getDeclaredMethods();获得类中的所有成员方法对象,返回数组,只获得本类申明的方法。

测试类

public class Dog {private String name ;public Dog(){}public Dog(String name) {this.name = name;}public void run(){System.out.println("狗跑的贼快~~");}private void eat(){System.out.println("狗吃骨头");}private String eat(String name){System.out.println("狗吃" + name);return "吃的很开心!";}public static void inAddr(){System.out.println("在黑马学习Java!");}public String getName() {return name;}public void setName(String name) {this.name = name;}}

6.1 获取所有方法

@Test
public void getDeclaredMethods(){Class clazz = Dog.class;Method[] methods = clazz.getDeclaredMethods();for (Method method : methods) {System.out.println(method.getName() +" 返回值类型:" + method.getReturnType() + " 参数个数:" + method.getParameterCount());}
}

输出

getName 返回值类型:class java.lang.String 参数个数:0
run 返回值类型:void 参数个数:0
setName 返回值类型:void 参数个数:1
inAddr 返回值类型:void 参数个数:0
eat 返回值类型:void 参数个数:0
eat 返回值类型:class java.lang.String 参数个数:1

6.2 获取单个方法并执行

@Test
public void getDeclardMethod() throws Exception {Class clazz = Dog.class;Method m = clazz.getDeclaredMethod("eat");Method m2 = clazz.getDeclaredMethod("eat", String.class);m.setAccessible(true);m2.setAccessible(true);Dog d = new Dog();Object result = m.invoke(d);System.out.println(result);Object result2 = m2.invoke(d, "骨头");System.out.println(result2);
}

输出

狗吃骨头
null
狗吃骨头
吃的很开心!

7 总结

反射提供了一种运行时获取类信息并操作的机制,增大了Java代码的灵活性,但是同时也破坏了封装特性,因为可以反射获取private类型的数据。
反射主要涉及Class、Field、Constructor、Method这几个对象的使用。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

看完这篇 教你玩转渗透测试靶机Vulnhub——Momentum:2

Vulnhub靶机Momentum:2渗透测试详解 Vulnhub靶机介绍&#xff1a;Vulnhub靶机下载&#xff1a;Vulnhub靶机安装&#xff1a;Vulnhub靶机漏洞详解&#xff1a;①&#xff1a;信息收集&#xff1a;②&#xff1a;漏洞发现&#xff1a;③&#xff1a;文件上传漏洞利用&#xff1a;…

Mysql--事务

事务 开始之前&#xff0c;让我们先想一个场景&#xff0c;有的时候&#xff0c;为了完成某个工作&#xff0c;需要完成多种sql操作 比如转账 再比如下单 第一步 我的账户余额减少 第二步 商品的库存要减少 第三步 订单表中要新增一项 事务的本质&#xff0c;就是为了把多个操…

jmeter While控制器

一种常见的循环控制语句&#xff0c;用于重复执行一段代码块&#xff0c;直到指定的条件不再满足。 参数&#xff1a; 空LASTJMeter变量、函数、属性或任意其他可用表达式 &#xff08;jmeter提供的方法&#xff09;。判断变量值count_num小于等于20&#xff0c;推荐简单的几…

Django+Nginx+uWSGI+Supervisor实战

大家好&#xff0c;真的是许久没有更新文章了&#xff0c;甚是想念&#xff0c;最近这段时间事情很多&#xff0c;家里的事情、工作的事情&#xff0c;真没有太多时间去码文章&#xff0c;其实已经搁置了些许文章&#xff0c;没有整理&#xff0c;趁着这段时间风平浪静&#xf…

sublime text 格式化json快捷键配置

以 controlcommandj 为例。 打开Sublime Text&#xff0c;依次点击左上角菜单Sublime Text->Preferences->Key Bindings&#xff0c;出现以下文件&#xff1a; 左边的是Sublime Text默认的快捷键&#xff0c;不可编辑。右边是我们自定义快捷键的地方&#xff0c;在中括号…

Ubuntu-22.04通过RDP协议连接远程桌面

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、RDP是什么&#xff1f;二、配置1.打开远程桌面功能2.验证服务3.防火墙配置4.测试效果 总结 前言 由于一些特殊需要&#xff0c;我需要通过远程桌面连接到U…

谈论浏览器内核

浏览器内核是指浏览器使用的渲染引擎&#xff0c;用于解析并显示网页的内容。主要有以下几种浏览器内核&#xff1a; Trident&#xff08;IE内核&#xff09;&#xff1a;由Microsoft开发&#xff0c;被用于Internet Explorer浏览器。目前已经被Edge取代。 Gecko&#xff1a;…

解密外贸邮箱:揭秘其优势与出奇招!

外贸业务需要面对来自全球范围内的客户和供应商&#xff0c;因此&#xff0c;拥有一个高效可靠的通讯工具非常重要。在这方面&#xff0c;外贸邮箱无疑成为了外贸业务中不可或缺的一部分。那么&#xff0c;外贸邮箱有哪些优势呢&#xff1f;在这篇文章中&#xff0c;我们将会全…

2672. 有相同颜色的相邻元素数目;1947. 最大兼容性评分和;958. 二叉树的完全性检验

2672. 有相同颜色的相邻元素数目 核心思想&#xff1a;枚举。每次操作只会影响index左右两边的数&#xff0c;所以我们只需要判断操作前index左右是否存在相同的数&#xff0c;然后减少一&#xff1b;然后将颜色修改&#xff0c;然后判断修改后index左右相邻的数是否是相同的&…

帆软报表简单设置分组汇总

前言 接手之前同事留下的一个胶膜产品入库登记表&#xff08;帆软报表&#xff09;&#xff0c;结果手滑把原来的报表行删除了。用户反馈需要恢复按报表中 “型号” “卷数” 分组汇总一下 “件数” 字段的值、也就是按每种同型号同卷数分组、相同分组的要有一行汇总&#xf…

路由缓存问题 | vue-router的导航守卫

路由缓存问题 带参路由&#xff0c;当参数发生变化时&#xff0c;相同的组件实例将被复用&#xff0c;组件的生命周期钩子不会被调用&#xff0c;导致数据无法更新。 两种解决方法&#xff1a; 1. 给 RouterView绑定key值&#xff0c;即 <RouterView :key"$route.ful…

软件测试中的43个功能测试点总结

功能测试就是对产品的各功能进行验证&#xff0c;根据功能测试用例&#xff0c;逐项测试&#xff0c;检查产品是否达到用户要求的功能。针对web系统的常用测试方法如下&#xff1a; 1、页面链接检查&#xff1a; 每一个链接是否都有对应的页面&#xff0c;并且页面之间切换正…

计算机竞赛 基于深度学习的人脸表情识别

文章目录 0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术 2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的人脸表情识别 该项目较…

C#使用proto

写多了go代码&#xff0c;被go mod tidy惯坏了&#xff0c;还以为全天下的都很好用呢&#xff0c;结果发现并不是这样。尤其是项目组的proto还是又封了个工具直接就能跑得&#xff0c;导致以为没那么复杂的事情变得复杂了起来。是有两套生成的规则&#xff0c;时间有点晚&#…

Leetcode 1572.矩阵对角线元素之和

给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;25 解释&#xff1a;对角线的和为&#xff…

Boost电路实战详解!(高效率同步整流,PID闭环追踪)

文章目录 寄语什么是BOOST电路BOOST同步升压电路设计要求设计方案驱动电路电压采样电路 总体电路代码实物图总结 寄语 提示&#xff1a;若想实战演练&#xff0c;请先熟悉文章操作流程哦&#xff0c;不然会有危险&#xff01;&#xff01; 我建了一个群&#xff0c;分享我个人…

Hadoop生态圈中的Hive数据仓库技术

Hadoop生态圈中的Hive数据仓库技术 一、Hive数据仓库的基本概念二、Hive的架构组成三、Hive和数据库的区别四、Hive的安装部署五、Hive的基本使用六、Hive的元数据库的配置问题七、Hive的相关配置项八、Hive的基本使用方式1、Hive的命令行客户端的使用2、使用hiveserver2方法操…

Inno Setup 打包的文件以管理员权限运行

在 Inno Setup 安装目录中找到文件 SetupLdr.e32&#xff0c;用软件 ResourceHacker 打开。如下图&#xff0c;点开清单&#xff0c;找到 <requestedExecutionLevel level"asInvoker" uiAccess"false"/></requestedPrivileges>改为 <requ…

hadoop-MapReduce

分布式计算模型MapReduce 1.理解MapReduce设计思想 2.理解MapReduce分布式计算的基本原理 3.掌握使用Java进行MapReduce编程 4.掌握在Hadoop集群中提交MapReduce任务 1. MapReduce设计思想 1.1 什么是MapReduce 1&#xff09;MapReduce是一个分布式计算框架 它将大型数据操作…

【MySQL】数据库基础知识

本文基于Linux的MySQL 文章目录 一. 什么是数据库二. 主流数据库三. 服务器&#xff0c;数据库和表的关系四. MySQL架构五. SQL语句分类结束语 一. 什么是数据库 数据库本质是对数据内容存储的一套解决方案 如何理解呢&#xff1f; 首先&#xff0c;说到数据内容存储&#xff…