一.反射介绍
1.在Java-反射机制是什么?
Java反射是指在程序运行期间,能够查看、检测和修改程序本身的状态或行为。在Java中,反射机制的核心是反射API,这是一组可以让你在运行期间获取类和对象信息的API。这些API使你可以检查对象、获取类属性和方法、调用对象方法,以及创建对象实例。
反射API的核心是java.lang.reflect包,该包包含了三个重要的类:Field、Method和Constructor。使用这些类及其相关方法,可以针对某个对象或类进行操作。
反射技术的优点是可以让我们在运行期间创建、检查和操作任何一个类的对象,而且不需要知道该类的具体实现。反射的应用场景比较多,比如:框架开发、Web应用程序开发、注解和自定义注解处理、组件化开发、RPC(远程过程调用)等。
2.Java-反射机制有什么作用
Java反射机制在Java语言中拥有很重要的作用,一些常见的作用分别是:
1. 获取类对象和类信息
使用反射机制可以在运行时获取对象的类信息,包括类名、父类、接口、构造方法、方法、字段等信息。这在类库、框架、组件化开发中尤为重要,可以在不知道类名和类实现的情况下,动态地获取类信息,使用灵活。比如,通过外部配置文件或者在线获取类名,可以反射出对应的类名,然后直接获取该类的实例对象,实现对该类的操作。
2. 动态创建对象和调用方法
使用反射机制可以在运行时动态地创建一个类的对象,并且可以在任何时候调用一个方法。通过在运行期间动态获得方法名、参数类型和返回类型等信息,可以调用不同类的同名方法。这在框架中有广泛应用,可以实现自动化构建,自适应扩展等功能。
3. 实现注解和代理
使用反射机制可以实现注解和代理。通过读取注解信息,可以获取注解中定义的属性和方法,从而实现自定义注解的应用。通过代理,可以实现AOP(面向切面编程)和自动化代理等功能,大大提高代码复用性和可维护性。
4. 实现动态代理
动态代理是通过反射机制实现的,可以在运行期间动态地生成代理对象,实现对不同类的动态代理,弥补了Java单继承的不足。动态代理在AOP中使用广泛,可以在运行时动态地添加一些公共的代码逻辑,比如安全检查、事务管理、日志记录等。
总之,Java反射机制在Java语言中有很重要的作用,可以实现许多灵活性强、可扩展性强、易于维护的功能。它不仅仅限于框架开发、Web应用程序开发、注解和自定义注解处理、组件化开发、RPC(远程过程调用)等领域,还可以应用到很多其他的领域中。
二.反射应用
1.什么叫类类?
在Java中,反射机制是指程序可以在运行时获取和操作Java程序的类、对象、方法等信息的能力。在Java反射中,“类”是一种重要的概念。
1.1 类类的获取方式:一起反射从获取类对象开始
1.1.1代码截屏:
1.1.2源码:
package com.lz.demo; public class demo2 { // 类类的获取方式:一起反射从获取类对象开始 // 1.Class.forName 数据库连接需要 // 2.实例化的类名字.getClass() // 3.类名.class public static void main(String[] args) throws Exception { Student stu=new Student(); //jdbc 数据库连接需要 Class c1=Class.forName("com.lz.demo.Student"); System.out.println(c1); //通用增删改 Class c2=stu.getClass(); System.out.println(c2); //通用查询 Class c3=Student.class; System.out.println(c3); } }
1.1.3效果图:
1.1.4总结
上述三个例子分别展示了通过类的全限定名、对象和转义字符获取类对象的方式。
获取到类对象后,就可以使用Class类提供的方法,如getFields()、getDeclaredFields()、getMethods()、getDeclaredMethods()等,来获取和操作类的属性、方法等信息。
总之,在Java反射中,“类”是指使用Class类来获取和操作Java程序的类信息的概念。
2 反射实例化
2.1所有实体类添加有参构成器,一定要有无参构成器
因为和 super()相关
2.2实例
2.2.1代码截图
2.2.2代码效果:
2.2.3源码:
package com.lz.demo; import java.lang.reflect.Constructor; public class demo3 { public static void main(String[] args) throws Exception { /** * 反射实例化 * 所有实体类添加有参构成器,一定要有无参构成器 * super()相关 * */ //一切反射和类类相关 Class c=Class.forName("com.lz.demo.Student"); //调用没有参数构造器 Student s1=(Student) c.newInstance(); System.out.println(s1); //调用有一个参数构造器 // parameterizedTypes参数类型 Constructor cr1=c.getConstructor(String.class); Student s2 = (Student) cr1.newInstance("s001"); System.out.println(s2); //调用有2个参数构造器 Constructor cr2=c.getConstructor(String.class,String.class); Student s3 = (Student) cr2.newInstance("s001","nb"); System.out.println(s3); //私有化调用有一个参数构造器 // Constructor cr3=c.getConstructor(Integer.class); // java.lang.NoSuchMethodException: com.lz.demo.Student.<init>(java.lang.Integer) // getConstructo 公有 Constructor cr3=c.getDeclaredConstructor(Integer.class); cr3.setAccessible(true);//打开私有化访问权限 Student s4 = (Student) cr3.newInstance(18); // java.lang.IllegalAccessException: Class com.lz.demo.demo3 can not access a member of class com.lz.demo.Student with modifiers "private" //私有化不可调用 System.out.println(s4); } }
3.反射动态方法调用
3.1代码截屏:
3.2效果图:
3.3源码:
package com.lz.demo; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class demo4 { public static void main(String[] args) throws Exception { /** * 反射动态方法调用 */ Class c=Student.class; Student s1=(Student) c.newInstance(); //调用没有参数方法name 方法名 parameterizedTypes 参数类型 Method m1=c.getMethod("hello"); //obj:类实例 args:参数值 invoke:方法返回值 Object invoke = m1.invoke(s1); System.out.println(invoke); //调用有一个参数构方法 Method m2=c.getMethod("hello",String.class); //obj:类实例 args:参数值 invoke:方法返回值 Object invoke2 = m2.invoke(s1,"nb"); System.out.println(invoke2); //私有化调用有一个参数构造器 Method m3=c.getDeclaredMethod("add",Integer.class,Integer.class); m3.setAccessible(true); Object invoke3 = m3.invoke(s1, 1,2); System.out.println(invoke3); } }
4.反射读写属性
4.1代码截屏:
4.2效果图
4.3源码:
package com.lz.demo; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class demo5 { public static void main(String[] args) throws Exception { /** * 反射读写属性 */ Class c=Student.class; Student student = new Student("s1", "nb"); student.age=13; //传统 System.out.println(student.getSid()); System.out.println(student.getSname()); //反射优点 System.out.println("-----------------"); Field name = c.getDeclaredField("sname"); name.setAccessible(true); name.set(student, "lz"); Field[] Fields = c.getDeclaredFields(); for (Field field : Fields) { field.setAccessible(true); System.out.println(field.getName()+":"+field.get(student)); } //缺点当字段名有很多是就有缺点 /* *在servelt传输数据是就会有这样的情况 *request.getParementer("id") * *Student s = new Student(); *s.setid *s.setname *..... */ } }