反射【获取class对象、 操作属性、方法】

day38下

反射

前言

使用到一个类,JVM会将该类的class文件加载到方法区(类加载机制),

同时会在堆内存中创建该类的class对象,class对象的作为class文件的访问入口

Java的反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

理解:

反射实际上就是获取class对象,通过class对象访问class文件中的内容

访问内容:

  1. 属性
  2. 构造方法
  3. 普通方法(成员方法、静态方法、抽象方法…)
  4. 方法上的参数
  5. 方法上的返回值
  6. 数组

关键点-获取Class文件对象

利用反射获取class对象

问:class文件中包含了什么内容?
class文件包含了该类所有的信息

注意:

该类的class文件只在一次到方法区中,

该类的class对象在程序中是唯一的。

所以不管使用那种方式获取class对象都是同一个

public class Test01 {public static void main(String[] args) throws ClassNotFoundException {//获取class对象方式1Class<? extends Student> clazz1 = Student.class;//获取class对象方式2Student stu = new Student();Class<? extends Student> clazz2 = stu.getClass();//获取class方式3Class<?> clazz3 = Class.forName("com.qf.reflex01.Student");System.out.println(clazz1 == clazz2);//trueSystem.out.println(clazz1 == clazz3);//true}
}

问:那种方法更好?

推荐path的获取方法更好,使用配置文件,可维护性更高;
但是根据不同情况相应使用三种方法

经验:配置文件 + Class.forName()

public class Test02 {public static void main(String[] args) throws IOException, ClassNotFoundException {Properties p = new Properties();p.load(Test02.class.getClassLoader().getResourceAsStream("classPath.properties"));String path = p.getProperty("path");Class<?> clazz = Class.forName(path);System.out.println(clazz);}
}
配置文件
//配置文件:classPath.properties文件
path=com.qf.reflex01.Student

注意:

父类子类都有toString情况,注意子类toString的重写【自动生成时注意添加父类的toString,不然可能出现输出不了对应预想的结果】

下面操作属性就会出现

public class Person {private String name;private char sex;private int age;//有参、无参构造、get、set、toString方法【略】}
public class Student extends Person{private String classId;private String id;public static final String str = "风华雪月";//有参、无参构造、get、set、toString方法【略】}

反射访问内容

反射操作注意设置权限

操作属性

带Declared的方法都能获取私有的
乱填属性名未匹配对应属性异常(用try-catch)
属性参数值=修饰符值累加(数字)判断其修饰情况(即用什么修饰)4

操作属性方式:

直接设置属性(set方法,前提类和对象都有)
通过反射设置属性(优点:后面配置文件设置,底层自动创建类和对象)

public class Test03 {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {//		Properties p = new Properties();
//		p.load(Test03.class.getClassLoader().getResourceAsStream("classPath.properties"));
//		String path = p.getProperty("path");//		Class<?> clazz = Class.forName(path);//获取本类及其父类公有的属性对象
//		Field[] fields = clazz.getFields();
//		for (Field field : fields) {
//			System.out.println(field);
//		}//获取本类所有的属性对象
//		Field[] fields = clazz.getDeclaredFields();
//		for (Field field : fields) {
//			System.out.println(field);
//		}//获取本类及其父类所有的属性对象
//		for(Class<?> c = clazz;c!=null;c=c.getSuperclass()){
//			Field[] fields = c.getDeclaredFields();
//			for (Field field : fields) {
//				System.out.println(field);
//			}
//		}//		try {
//			//获取本类指定的属性对象
//			Field field = clazz.getDeclaredField("str");
//			System.out.println(field);
//			
//			//获取属性参数值
//			int modifiers = field.getModifiers();
//			System.out.println("是否使用public修饰:" + Modifier.isPublic(modifiers));
//			System.out.println("是否使用stati修饰:" + Modifier.isStatic(modifiers));
//			System.out.println("是否使用final修饰:" + Modifier.isFinal(modifiers));
//			System.out.println("是否使用private修饰:" + Modifier.isPrivate(modifiers));
//			System.out.println("是否使用protected修饰:" + Modifier.isProtected(modifiers));
//			System.out.println("是否使用transient修饰:" + Modifier.isTransient(modifiers));
//			
//		} catch (NoSuchFieldException e) {//属性名没有配到对应的属性就报该异常
//			e.printStackTrace();
//		} catch (SecurityException e) {
//			e.printStackTrace();
//		}//通过反射设置对象里的属性
//		Student stu = new Student("奇男子", '男', 23, "2401", "001");
//		Field field = clazz.getDeclaredField("id");
//		field.setAccessible(true);//设置修改权限
//		field.set(stu, "666");//设置stu对象里的id属性为"666"的值
//		System.out.println(stu);//通过反射工具类设置对象里的属性Student stu = new Student();ReflexUtil.setField(stu, "name", "奇男子");ReflexUtil.setField(stu, "sex", '男');ReflexUtil.setField(stu, "age", 23);ReflexUtil.setField(stu, "classId", "2401");ReflexUtil.setField(stu, "id", "001");System.out.println(stu);}
}
反射的工具类

utils包下

这里反射工具类写了获取和设置的方法【这里获取属性用到getClass()更方便】

public class ReflexUtil {/*** 获取当前类及其父类的属性对象* @param clazz class对象* @param name 属性名* @return 属性对象*/public static Field getField(Class<?> clazz,String name){for(Class<?> c = clazz;c != null;c = c.getSuperclass()){try {Field field = c.getDeclaredField(name);return field;} catch (NoSuchFieldException e) {} catch (SecurityException e) {}}return null;}/*** 设置对象中的属性* @param obj 对象* @param name 属性名* @param value 属性值*/public static void setField(Object obj,String name,Object value){Field field = getField(obj.getClass(), name);if(field != null){field.setAccessible(true);try {field.set(obj, value);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}/*** 创建对象* @param clazz class对象* @param paremeterType 构造方法中的参数类型数组* @param paremeters 构造方法中的参数数据* @return 对象*/public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] paremeters){try {Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);constructor.setAccessible(true);T obj = constructor.newInstance(paremeters);return obj;} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}return null;}
}

操作方法

构造方法

不能获取父类的构造方法【一般考虑本类的构造方法】
反射工具类再添加创建对象的方法【外面传数组】

调用构造函数创建对象

public class Test04 {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {//		Properties p = new Properties();
//		p.load(Test04.class.getClassLoader().getResourceAsStream("classPath.properties"));
//		String path = p.getProperty("path");//		Class<?> clazz = Class.forName(path);//获取该类公有的构造方法对象
//		Constructor<?>[] constructors = clazz.getConstructors();
//		for (Constructor<?> constructor : constructors) {
//			System.out.println(constructor);
//		}//获取该类所有的构造方法对象
//		Constructor<?>[] constructors = clazz.getDeclaredConstructors();
//		for (Constructor<?> constructor : constructors) {
//			System.out.println(constructor);
//		}//获取无参构造对象
//		Constructor<?> constructor = clazz.getDeclaredConstructor();
//		//利用无参构造对象创建该类的对象
//		constructor.setAccessible(true);//设置修改权限
//		Student stu = (Student) constructor.newInstance();
//		System.out.println(stu);//利用无参构造对象创建该类的对象 -- 简化版
//		Student stu = (Student) clazz.newInstance();
//		System.out.println(stu);//获取有参构造对象
//		Constructor<?> constructor = clazz.getDeclaredConstructor(String.class,char.class,int.class,String.class,String.class);
//		//利用有参构造对象创建该类的对象
//		constructor.setAccessible(true);//设置修改权限
//		Student stu = (Student) constructor.newInstance("奇男子",'男',23,"2401","001");
//		System.out.println(stu);//利用反射工具类去创建对象 -- 底层调用无参构造
//		Student stu = ReflexUtil.newInstance(Student.class, null, null);
//		System.out.println(stu);//利用反射工具类去创建对象 -- 底层调用有参构造Class<?>[] parameterTypes = {String.class,char.class,int.class,String.class,String.class};Object[] paremeters = {"奇男子",'男',23,"2401","001"};Student stu = ReflexUtil.newInstance(Student.class, parameterTypes, paremeters);System.out.println(stu);}
}
普通方法

操作数组

操作泛型

反射的实际应用

总结

3.反射 — 重要!!!
获取class对象
操作属性
操作方法
注意:封装反射的工具类

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

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

相关文章

在STM32中给固定的地址写入一个值,并通过memory窗口进行查看

首先对STM32中存储数据的地方有一个了解 一个是FLASH,一个是RAM RAM是易失存储器&#xff0c;FLASH是非易失存储器&#xff0c;这是最直观的解释。 主要记住以下几点&#xff1a; RAM&#xff08;随机存储器&#xff09;&#xff1a;既可以从中读取数据&#xff0c;也可以写…

GitHub repository - commits - branches - releases - contributors

GitHub repository - commits - branches - releases - contributors 1. commits2. branches3. releases4. contributorsReferences 1. commits 在这里可以查看当前分支的提交历史。左侧的数字表示提交数。 2. branches 可以查看仓库的分支列表。左侧的数字表示当前拥有的分…

AppBuilder升级!工作流编排正式上线!AssistantsAPI开放邀测!

>>【v0.5.3版本】 上线时间&#xff1a;2024/4/14 关键发版信息&#xff1a; 低代码态&#xff1a;新增工作流&#xff0c;低代码制作组件 自定义组件&#xff1a;支持用户自定义创建组件&#xff0c;并被Agent自动编排调用
 工作流框架&#xff1a;组件支持流式编排…

总会有那个干出来的人,为什么不能是我?

在这个充满挑战和不确定性的时代&#xff0c;焦虑似乎成了我们生活的常态。无论是职场竞争、学业压力还是人际关系&#xff0c;我们都可能感到焦虑和不安。然而&#xff0c;真正的问题不在于焦虑本身&#xff0c;而在于我们如何应对它。本文将探讨如何通过面对恐惧、研究解决方…

【QT教程】QT6单元测试

QT6单元测试 使用AI技术辅助生成 QT界面美化视频课程 QT性能优化视频课程 QT原理与源码分析视频课程 QT QML C扩展开发视频课程 免费QT视频课程 您可以看免费1000个QT技术视频 免费QT视频课程 QT统计图和QT数据可视化视频免费看 免费QT视频课程 QT性能优化视频免费看 免费QT视…

rman 归档备份 archived log 不重复备份

11.2.0.3数据库环境&#xff0c;使用rman进行归档日志备份&#xff0c;想实现&#xff1a; (1)每天备份归档日志&#xff0c;备份完并不删除归档日志 (2)归档日志备份成功一次之后&#xff0c;下次再备份的时候rman就自动不会再次备份这个归档日志 这个需求可以通过 backup …

全视通智慧门诊方案助力满洲里市人民医院实现“医”路畅通

近年来&#xff0c;国家有关部门出台多项政策&#xff0c;意在进一步优化医疗服务&#xff0c;提升患者体验&#xff0c;不断满足人民群众日益增长的美好生活需要。 2019年&#xff0c;《医院智慧服务分级评估标准体系&#xff08;试行&#xff09;&#xff08;2019版&#xf…

DataGrip数据库管理工具安装使用

DataGrip数据库管理工具安装使用 DataGrip介绍 DataGrip是jetbrains旗下的一款数据库管理工具&#xff0c;相信做过java开发的同学都知道&#xff0c;idea就是这家公司发明的。 DataGrip 是JetBrains公司开发的数据库管理客户端工具&#xff08;操作数据库的IDE&#xff0c;…

Meta新一代AI芯片亮相

作为其对人工智能应用投资的一部分&#xff0c;Meta去年还开发了一种定制芯片——Meta Training and Inference Accelerator&#xff0c;或MTIA&#xff0c;用于其数据中心在其流行平台上运行人工智能产品&#xff0c;包括Facebook、Instagram和WhatsApp&#xff0c;并训练其人…

C语言练习:变种水仙花数

今天让我们来看看变种的水仙花吧&#xff0c;话不多说&#xff0c;直入主题。 题目描述 变种水仙花数- Lily Number: 把任意的数字&#xff0c;从中间拆分成两个数字&#xff0c;比如1461可 以拆分成(1和461)&#xff0c;(14和61)&#xff0c;(146和1),如果所有拆分后的乘积之和…

Linux: network: icmp with unreachable - admin prohibited filter

最近遇到一个问题&#xff0c;就是对方返回icmp&#xff1a;unreachable - admin prohibited filter&#xff0c;这个错误。是从tcpdump里显示出来的&#xff0c;根据tcpdump的源代码查看&#xff1a; /* rfc1716 */ #ifndef ICMP_UNREACH_FILTER_PROHIB #define ICMP_UNREACH…

Es批量删除DeleteByQueryRequestBuilder

一、DeleteByQueryRequestBuilder DeleteByQueryRequestBuilder是Elasticsearch Java客户端中的一个类&#xff0c;用于构建和执行基于查询条件删除文档的请求。实验结果表明&#xff1a;删除速率大概是每秒3万条左右。 DeleteByQueryRequestBuilder类提供了一种方便的方式来…

Java中的System

文章目录 概要小结 概要 在Java中&#xff0c;System类提供了一些静态方法来实现与系统相关的操作。以下是System类中常用的方法及其含义&#xff1a; System.currentTimeMillis()&#xff1a;返回当前时间&#xff08;以毫秒为单位&#xff09;自1970年1月1日00:00:00 GMT以来…

硬盘当前用户无权限、主机名修改...

将文件夹的权限从root变更为当前用户 su rootchown -R admin1 /media/admin1/hdd1/media/admin1/hdd1为硬盘挂载目录 在 Linux 中使用 /etc/hostname 来更改主机名 除了上面的方法外&#xff0c;我们还可以通过修改 /etc/hostname 文件来达到修改主机名的目的。但这个方法需…

Python中的字典(dict)与集合(set):核心数据结构的比较与应用

Python中的字典&#xff08;dict&#xff09;与集合&#xff08;set&#xff09;&#xff1a;核心数据结构的比较与应用 在Python编程中&#xff0c;字典&#xff08;dict&#xff09;和集合&#xff08;set&#xff09;是两种非常重要的内置数据结构&#xff0c;它们在处理数…

企业管理员工微信必备

在微信私域管理系统后台&#xff0c;管理员可以对销售工作微信进行实时监管&#xff0c;以确保业务员的微信使用符合工作要求&#xff0c;并避免资源的浪费。通过监管业务员在手机端微信的一举一动&#xff0c;包括发送会话的次数、接收消息的次数、添加好友的数据等&#xff0…

芯片低功耗VCLP

​VCLP&#xff08;VC Low Power&#xff09;是Synopsys提供的一款低功耗静态规则检查工具&#xff0c;它能够帮助验证和清洁IEEE 1801 Unified Power Format (UPF)低功耗设计意图&#xff0c;并确保UPF中的功耗意图与实现一致。VCLP通过执行语法和语义检查&#xff0c;有助于在…

【重装系统】分配D盘

1.右键“此电脑”&#xff0c;点击管理 2.选择“存储”–磁盘管理 3.右键未分配磁盘–新建简单卷 4.一路默认设置即可

企业网站建设需要了解什么

在现代商业环境中&#xff0c;企业网站已经成为企业宣传、推广和销售的重要工具。企业网站的建设需要考虑多个因素&#xff0c;包括以下几个方面&#xff1a; 首先&#xff0c;了解企业的目标和定位。企业网站的建设应该围绕企业的目标和定位展开&#xff0c;以达到企业在市场中…

偏微分方程算法之混合边界差分

目录 一、研究对象 二、差分格式 2.1 向前欧拉格式 1. 中心差商 1.1.1 理论推导 1.1.2 算例实现 2. x0处向前差商&#xff0c;x1处向后差商 1.2.1 理论推导 1.2.2 算例实现 2.2 Crank-Nicolson格式 2.2.1 理论推导 2.2.2 算例实现 一、研究对象 这里我们以混合边界…