反射(Reflection) --Java学习笔记

2024-04-10 13:52

本文主要是介绍反射(Reflection) --Java学习笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

反射

  • 反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)

反射学什么?

学习获取类的信息、操作它们

  1. 反射第一步:加载类,获取类的字节码:Class对象
  2. 获取类的构造器:Constructor对象
  3. 获取类的成员变量:Field对象
  4. 获取类的成员方法:Method对象

全部认识完后,再看反射的应用场景

1、反射第一步:加载类,获取类的字节码:Class对象

获取Class对象的三种方式

  • Class c1=类名.class
  • 调用Class提供方法:  public static Class forName(String package)
  • Object提供的方法:  publicClass getClass();  Class c3=对象.getClass()

代码演示:

package com.zeyu.reflect;public class Test1Class {public static void main(String[] args) throws Exception {Class c1 = Student.class;System.out.println(c1.getName());   //全类名System.out.println(c1.getSimpleName()); //简名:StudentClass c2 = Class.forName("com.zeyu.reflect.Student");   //填全类名System.out.println(c1 == c2);   //拿到的是同一个对象Student s = new Student();  //创建类的实例Class c3 = s.getClass();    //调用getClass方法System.out.println(c3 == c2);   //拿到的依旧是同一个对象}
}

运行结果:

2、获取类的构造器:Constructor对象

Class提供了从类中获取构造器的方法

获取类构造器的作用:依然是初始化对象返回

代码演示:

package com.zeyu.reflect;import org.junit.Test;import java.lang.reflect.Constructor;public class Test2Constructor {@Testpublic void testGetConstructors() {//1、反射第一步,必须先得到这个类的class对象Class c = Cat.class;//2、获取类的全部构造器
//        Constructor[] constructors = c.getConstructors();   //只能拿public类型的构造器Constructor[] constructors = c.getDeclaredConstructors();//3、遍历数组中的每一个构造器对象for (Constructor constructor : constructors) {System.out.println(constructor.getName() + "-->" + constructor.getParameterCount());}}@Testpublic void testGetConstructor() throws Exception {//1、反射第一步,必须先得到这个类的class对象Class c = Cat.class;//2、获取某一个构造器:无参构造器
//            Constructor constructor = c.getConstructor(); //只能拿public类型的构造器Constructor constructor = c.getDeclaredConstructor();   //存在就能拿到System.out.println(constructor.getName() + "-->" + constructor.getParameterCount());constructor.setAccessible(true);    //禁止检查访问权限Cat cat = (Cat) constructor.newInstance();  //调用构造器完成对象初始化System.out.println(cat);//获取有参构造器Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);System.out.println(constructor2.getName() + "-->" + constructor2.getParameterCount());constructor2.setAccessible(true);Object cat2 = constructor2.newInstance("黑猫警长", 3);  //初始化对象System.out.println(cat2);}
}

运行结果:

也可以用反射破坏单例设计模式

3、获取类的成员变量:Field对象

Class提供了从类中获取成员变量的方法

获取到成员变量的作用:依然是赋值、取值

代码演示:

package com.zeyu.reflect;import org.junit.Test;import java.lang.reflect.Field;public class Test3Field {@Testpublic void testGetFields() throws Exception {//反射第一步,必须先拿到类的class对象Class c = Cat.class;//获取类的全部成员变量Field[] fields = c.getDeclaredFields();//遍历这个成员变量数组for (Field field : fields) {System.out.println(field.getName() + "--->" + field.getType());}//拿到某个成员变量Field fName = c.getDeclaredField("name");System.out.println(fName.getName() + "--->" + fName.getType());Field fAge = c.getDeclaredField("age");System.out.println(fAge.getName() + "--->" + fAge.getType());//赋值Cat cat = new Cat();fName.setAccessible(true);    //暴力访问fName.set(cat,"小橘");System.out.println(cat);//取值String name = (String) fName.get(cat);System.out.println(name);}
}

运行结果:

4、获取类的成员方法:Method对象

Class提供了从类中获取成员方法的API

成员方法的作用:依然是执行

代码演示:

package com.zeyu.reflect;import org.junit.Test;import java.lang.reflect.Method;public class Test4Methods {@Testpublic void TestGetMethods() throws Exception {//1、反射第一步,先得到类的class对象Class c = Cat.class;//2、获取类的全部成员方法Method[] methods = c.getDeclaredMethods();//3、遍历这个数组的每个方法对象for (Method method : methods) {               //getParameterCount()统计形参个数System.out.println(method.getName() + "--->" + method.getParameterCount() + "--->"+ method.getReturnType());}//4、获取某个方法对象Method run = c.getDeclaredMethod("run");System.out.println(run.getName() + "--->" + run.getParameterCount() + "--->"+ run.getReturnType());Method eat = c.getDeclaredMethod("eat", String.class);System.out.println(eat.getName() + "--->" + eat.getParameterCount() + "--->"+ eat.getReturnType());Cat cat = new Cat();run.setAccessible(true);    //禁止检查访问权限Object rs = run.invoke(cat);//调用无参run方法,用cat对象调用System.out.println(rs); //无返回值,返回结果为空eat.setAccessible(true);Object rs2 = (String) eat.invoke(cat, "鱼");System.out.println(rs2);}
}

运行结果:

反射的作用?

  • 基本作用:可以得到一个类的全部成分然后操作
  • 可以破坏封装性
  • 最重要的用途是:适合做lava的框架,基本上,丰流的框架都会基于反射设计出一些通用的功能

案例:使用反射做一个简易版的框架

需求:
对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去

实现步骤

  1. 定义一个方法,可以接收任意对象
  2. 每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量
  3. 遍历成员变量,然后提取成员变量在该对象中的具体值
  4. 把成员变量名、和其值,写出到文件中去即可

代码演示:

实现类:

package com.zeyu.reflect;import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;public class ObjectFrame {//保存任意对象的字段和数据到文件中去public static void saveObject(Object obj) throws Exception {PrintStream ps = new PrintStream(new FileOutputStream("src\\com\\zeyu\\reflect\\data.txt",true));//obj是任意对象,到底有多少字段需要保存Class c = obj.getClass();String cname = c.getSimpleName();ps.println("------------------" + cname + "------------------");//从这个类中提取它的全部成员变量Field[] fields = c.getDeclaredFields();//遍历每个成员变量for (Field field : fields) {field.setAccessible(true);//拿到成员变量的名字String name = field.getName();//拿到这个成员变量在对象中的数据String value = field.get(obj) + "";ps.println(name + "=" + value);}ps.close();}
}

测试类:

package com.zeyu.reflect;import org.junit.Test;public class Teat5ObjectFrame {@Testpublic void testSave() throws Exception {Cat cat = new Cat("小橘",2);Student s = new Student("小明","男",22,172.8);ObjectFrame.saveObject(cat);ObjectFrame.saveObject(s);}
}

运行结果:

这篇关于反射(Reflection) --Java学习笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/891241

相关文章

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

SpringBoot集成Milvus实现数据增删改查功能

《SpringBoot集成Milvus实现数据增删改查功能》milvus支持的语言比较多,支持python,Java,Go,node等开发语言,本文主要介绍如何使用Java语言,采用springboo... 目录1、Milvus基本概念2、添加maven依赖3、配置yml文件4、创建MilvusClient

浅析Java中如何优雅地处理null值

《浅析Java中如何优雅地处理null值》这篇文章主要为大家详细介绍了如何结合Lambda表达式和Optional,让Java更优雅地处理null值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录场景 1:不为 null 则执行场景 2:不为 null 则返回,为 null 则返回特定值或抛出异常场景

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

springboot项目中常用的工具类和api详解

《springboot项目中常用的工具类和api详解》在SpringBoot项目中,开发者通常会依赖一些工具类和API来简化开发、提高效率,以下是一些常用的工具类及其典型应用场景,涵盖Spring原生... 目录1. Spring Framework 自带工具类(1) StringUtils(2) Coll

SpringBoot条件注解核心作用与使用场景详解

《SpringBoot条件注解核心作用与使用场景详解》SpringBoot的条件注解为开发者提供了强大的动态配置能力,理解其原理和适用场景是构建灵活、可扩展应用的关键,本文将系统梳理所有常用的条件注... 目录引言一、条件注解的核心机制二、SpringBoot内置条件注解详解1、@ConditionalOn

通过Spring层面进行事务回滚的实现

《通过Spring层面进行事务回滚的实现》本文主要介绍了通过Spring层面进行事务回滚的实现,包括声明式事务和编程式事务,具有一定的参考价值,感兴趣的可以了解一下... 目录声明式事务回滚:1. 基础注解配置2. 指定回滚异常类型3. ​不回滚特殊场景编程式事务回滚:1. ​使用 TransactionT

Spring LDAP目录服务的使用示例

《SpringLDAP目录服务的使用示例》本文主要介绍了SpringLDAP目录服务的使用示例... 目录引言一、Spring LDAP基础二、LdapTemplate详解三、LDAP对象映射四、基本LDAP操作4.1 查询操作4.2 添加操作4.3 修改操作4.4 删除操作五、认证与授权六、高级特性与最佳