🥳🥳Welcome Huihui's Code World ! !🥳🥳
接下来看看由辉辉所写的关于反射机制的相关操作吧
目录
🥳🥳Welcome Huihui's Code World ! !🥳🥳
💡辉辉小贴士:反射有这么多优点,那么我们什么时候可以使用反射呢?
一.是什么
反射机制是Java语言中的一种高级特性,它可以在程序运行时动态获取类的信息、实例化对象、调用方法、访问和修改属性等。与之相对的是静态编译时期的程序设计方式,也是Java最初的设计方式
二.为什么要使用
反射机制在Java中十分重要,因为它提供了很多优秀的功能和特性
- 1. 动态地获取和使用类的信息
- 反射机制可以在程序运行时动态地获取类的信息,例如类的名称、字段、方法、注解等信息,从而进行一些动态操作,例如在JUnit中实现自动化测试时,通过反射获取类的所有测试方法,然后自动进行测试。
- 2. 动态地创建和使用类的实例对象
- 通过反射机制,我们可以动态地在程序运行时创建类的实例对象,这种方式使得代码更加灵活,可以根据业务需求动态地创建对象。例如在Spring框架中,就通过反射机制实现了依赖注入,并动态创建Bean实例。
- 3. 动态地调用和修改类的方法和字段
- 反射机制也可以处理类的方法和字段,通过反射机制,我们可以动态地调用和修改类的方法和字段,这种方式使得代码更加灵活和扩展性更强。例如在使用AOP技术时,就可以通过反射机制动态地调用目标方法,并实现一些统一的处理。
- 4. 实现更加灵活的框架和工具
- 反射机制可以为框架和工具提供更加灵活、可扩展和易用的接口,从而实现更加高效和智能的应用程序。例如在ORM框架中,通过反射机制可以将数据库中的表映射成Java类,从而实现快速地对表进行操作。
总而言之,反射机制可以为Java应用程序提供更加灵活、高效和智能的开发方式,通过反射机制,我们可以在程序运行时动态地调用和使用类的信息、方法和字段,从而实现更加高效和智能的应用程序
三.怎么使用
在学习怎么使用反射机制之前,我们需要知道Java反射机制的核心是Class类
💡辉辉小贴士:什么是Class类呢?
- 在Java的反射机制中,"类类"通常指Class类。Class类是Java中用来表示一个类的类
- 在Java程序运行时,每个类都会对于一个Class对象,Class对象包含了该类的各种元信息,例如类的名称、字段、方法等
- 借助Class对象,Java程序可以在运行时动态地创建类的实例、调用类的方法等操作,这就是反射机制的基本功能之一
- Class类中定义了很多方法,包括获取类的基本信息、实例化对象、获取字段和方法、修改字段和调用方法等,是Java反射机制的重要组成部分
上述描述还是太过于抽象,下面我们将通过代码更清晰的了解到什么是类类
package com.wh.reflect; public class Demo1 { /** * 什么是类类 */ // ①🐱猫类🐱里面会有很多的小猫,例如咪咪,加菲猫... // ②🐕狗类🐕里面也会有很多小狗,例如旺财,来福... // ③人类里面也会有很多小人,例如夏威大傻逼,王辉大美女 // 咪咪,加菲猫是猫类的实例 // 旺财,来福是狗类的实例 // 夏威大傻逼,王辉大美女是人类的实例 // 那么人类,狗类,猫类又是谁的实例呢? // 在这里我们就可以引入Class类的概念了:Class类是Java中用来表示一个类的类 // 所以人类,狗类,猫类都是Class类的实例!!!! /** * 1.2为什么要学习类类 * @throws Exception */ // 因为Class类是Java反射机制的基础之一 public static void main(String[] args) throws Exception { /** * 1.3怎么获取类类 */ Student stu = new Student(); //1.对象.getclass Class c1 = stu.getClass(); System.out.println(c1); //2.类名.class Class c2 = Student.class; System.out.println(c2);// class com.wh.reflect.Student //3.Class.forName("全路径名"); Class c3=Class.forName("com.wh.reflect.Student"); System.out.println(c3); } }
相信通过以上代码,我们已经能够了解到什么是类类了,那么接下来我们就看看反射机制到底怎么使用吧!!
对于反射机制的使用操作,全部以Student类作为实例👇👇
package com.wh.reflect; public class Student { private String sid; private String sname; public Integer age; static{ System.out.println("加载进jvm中!"); } public Student() { super(); System.out.println("调用无参构造方法创建了一个学生对象"); } public Student(String sid) { super(); this.sid = sid; System.out.println("调用带一个参数的构造方法创建了一个学生对象"); } public Student(String sid, String sname) { super(); this.sid = sid; this.sname = sname; System.out.println("调用带二个参数的构造方法创建了一个学生对象"); } @SuppressWarnings("unused") private Student(Integer age) { System.out.println("调用Student类私有的构造方法创建一个学生对象"); this.age = age; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public void hello() { System.out.println("你好!我是" + this.sname); } public void hello(String name) { System.out.println(name + "你好!我是" + this.sname); } @SuppressWarnings("unused") private Integer add(Integer a, Integer b) { return new Integer(a.intValue() + b.intValue()); } }
1.反射实例化
反射实例化的方法 newInstance() 来创建指定类的实例对象 getConstructor(Class) 调用公共的有参构造器,括号中的参数是构造器中的参数类型的类类 getDeclaredConstructor(Class) 调用私有的有参构造器,括号中的参数是构造器中的参数类型的类类 setAccessible(Boolean) 该方法用于设置方法、字段或者构造方法在访问时,是否需要在访问时取消Java语言访问修饰符的限制。也就是说,如果设置为 true,那么反射对象在使用时就不再需要考虑它的访问修饰符的限制。简而言之就是,可以调用到私有的方法、字段或者构造方法 package com.wh.reflect; import java.lang.reflect.Constructor; /** * 什么是反射? * 反射机制是Java语言中的一种高级特性, * 它可以在程序运行时动态获取类的信息、实例化对象、调用方法、访问和修改属性等。 * 与之相对的是静态编译时期的程序设计方式,也是Java最初的设计方式 * * 反射实例化 * * @author W * */ public class Demo2 { public static void main(String[] args) throws Exception { //一切反射从类类开始 Class cla =Class.forName("com.wh.reflect.Student"); //1.调用无参构造器【如果写了有参构造器,那么一定要记得补一个无参构造器】 Student stu1 = (Student) cla.newInstance();//调用无参构造方法创建了一个学生对象 System.out.println(stu1);//com.wh.reflect.Student@7852e922 //2.调用有一个参构造器 Constructor constructor1=cla.getConstructor(String.class); Student stu2 = (Student)constructor1.newInstance("wh1");//调用带一个参数的构造方法创建了一个学生对象 System.out.println(stu2);//com.wh.reflect.Student@4e25154f //3.调用带两个/多个参数的构造器 Constructor constructor2=cla.getConstructor(String.class,String.class); Student stu3 = (Student)constructor2.newInstance("wh1","王辉");//调用带二个参数的构造方法创建了一个学生对象 System.out.println(stu3);//com.wh.reflect.Student@70dea4e //4.调用私有的有一个参构造器的方法 Constructor constructor3=cla.getDeclaredConstructor(Integer.class); constructor3.setAccessible(true); Student stu4 = (Student) constructor3.newInstance(11);//调用Student类私有的构造方法创建一个学生对象 System.out.println(stu4);// com.wh.reflect.Student@5c647e05 } }
注意1:在我们使用newInstance()方法,去调用特定对象的无参构造器时,我们一定要保证其里面有无参构造器【如果写了有参构造器,那我们需要补一个无参构造器】
如果没有写无参构造器的话,那么将会抛出一个异常
注意2:在我们调用私有的方法、字段或者构造方法时,如果没有在调用之前使用setAccessible这个方法,则无法调用到私有的方法、字段或者构造方法,并且还会抛出一个异常
2.反射动态方法调用
反射动态方法调用中的方法 newInstance() 来创建指定类的实例对象 getMethod(String, Class...) 获取到特定对象中的共有的方法,第一个参数是方法的名字,第二个是一个可变参数,是该方法中的参数类型的类类 getDeclaredMethod(String, Class) 获取到特定对象中的私有的方法,第一个参数是方法的名字,第二个是一个可变参数,是该方法中的参数类型的类类 invoke(Object,Object... args) 根据传入的对象和参数,动态地在运行时调用指定对象的指定方法,返回的值是该方法的返回值,如果没有返回值,则该值为null setAccessible(Boolean) 该方法用于设置方法、字段或者构造方法在访问时,是否需要在访问时取消Java语言访问修饰符的限制。也就是说,如果设置为 true,那么反射对象在使用时就不再需要考虑它的访问修饰符的限制。简而言之就是,可以调用到私有的方法、字段或者构造方法 package com.wh.reflect; import java.lang.reflect.Method; /** * 什么是反射? * 反射机制是Java语言中的一种高级特性, * 它可以在程序运行时动态获取类的信息、实例化对象、调用方法、访问和修改属性等。 * 与之相对的是静态编译时期的程序设计方式,也是Java最初的设计方式 * * 反射动态方法调用 * @author W * */ public class Demo3 { public static void main(String[] args) throws Exception { // 一切反射从类类开始 Class cla = Class.forName("com.wh.reflect.Student"); Student stu = (Student) cla.newInstance(); // 1.调用无参方法 Method m1 = cla.getMethod("hello"); System.out.println(m1);// public void com.wh.reflect.Student.hello() Object invoke1 = m1.invoke(stu);// 你好!我是null System.out.println(invoke1);// null // 2.调用有参的方法 Method m2 = cla.getMethod("hello", String.class); System.out.println(m2);// public void com.wh.reflect.Student.hello(java.lang.String) Object invoke2 = m2.invoke(stu, "傻逼");// 傻逼你好!我是null System.out.println(invoke2);// null // 3.调用私有的有参方法 Method m3 = cla.getDeclaredMethod("add", Integer.class, Integer.class); System.out.println(m3);// private java.lang.Integer // com.wh.reflect.Student.add(java.lang.Integer,java.lang.Integer) m3.setAccessible(true); Object invoke3 = m3.invoke(stu, 1, 1); System.out.println(invoke3);// 2 } }
3.反射读写属性
反射读写属性所用到的方法 getDeclaredField(String) 拿到特定对象中特定的属性 getDeclaredFields() 拿到特定对象中所有的属性 getName() 拿到特定对象中所有的属性的属性名 get(Object) 拿到特定对象中所有的属性的属性值,传入的参数为特定对象的对象名 set(Object ,Object) 为指定对象修改指定的属性值 setAccessible(Boolean) 该方法用于设置方法、字段或者构造方法在访问时,是否需要在访问时取消Java语言访问修饰符的限制。也就是说,如果设置为 true,那么反射对象在使用时就不再需要考虑它的访问修饰符的限制。简而言之就是,可以调用到私有的方法、字段或者构造方法 package com.wh.reflect; import java.lang.reflect.Field; /** * 什么是反射? * 反射机制是Java语言中的一种高级特性, * 它可以在程序运行时动态获取类的信息、实例化对象、调用方法、访问和修改属性等。 * 与之相对的是静态编译时期的程序设计方式,也是Java最初的设计方式 * * 反射读写属性 * @author W * */ public class Demo4 { public static void main(String[] args) throws Exception { // 一切反射从类类开始 Class cla = Class.forName("com.wh.reflect.Student"); Student stu = new Student("wh2", "小王辉"); stu.age=22; /** * 修改对象中的属性 */ Field ageField = cla.getDeclaredField("age"); ageField.setAccessible(true); ageField.set(stu, 18); /** * 老版本:拿到student类的所有属性【也就是拿到某一个特定对象的所有的属性】 */ //以前用的方式 String sid = stu.getSid(); System.out.println(sid);//wh2 String sname = stu.getSname(); System.out.println(sname);//小王辉 /** * 新版本:拿到student类的所有属性【也就是拿到某一个特定对象的所有的属性】 */ Field[] declaredFields = cla.getDeclaredFields(); for (Field field : declaredFields) { field.setAccessible(true); System.out.println(field.getName()+":"+field.get(stu));//sid:wh2 sname:小王辉 age:22 } } }
💡辉辉小贴士:反射有这么多优点,那么我们什么时候可以使用反射呢?
那就让我们来看看它的应用场景吧!!
- 1. 依赖注入框架
- 依赖注入(DI)框架可以通过反射机制来创建实例对象,并通过注解或XML配置来设置对象的属性和方法。例如Spring框架中的@Autowired注解就是通过反射机制来实现依赖注入。
- 2. ORM框架
- 对象关系映射(ORM)框架可以通过反射机制来将数据库中的表映射成Java类,并进行相关的增删改查操作。例如Hibernate框架就是使用反射机制来将数据库表映射为Java对象。
- 3. 实现动态代理
- 动态代理技术可以通过反射机制动态生成代理对象,并进行相关的操作。例如在AOP编程中,就可以通过动态代理技术实现统一的日志、事务等操作。
- 4. 实现自动化测试
- 通过反射机制,可以在运行时获取类的信息和方法信息,从而实现自动化测试的功能。例如JUnit框架就是通过反射机制来获取测试类和测试方法的信息,并进行测试操作。
- 5. 实现插件化
- 通过反射机制,可以实现插件化的功能。例如在Eclipse IDE中,就可以通过定义扩展点和插件来实现插件化的功能。
好啦,今天的分享就到这了,希望能够帮到你呢!😊😊