Java反射
反射:框架设计的灵魂
框架:半成品软件,可以在框架的基础上进行软件开发,简化编码。
反射:将类的各个组成部分封装为其他对象,这就是反射机制。
好处:
1.在程序的运行过程中,去操作这些对象。
2.可以解耦,提高程序的可扩展性。
获取Class对象的方式:
1.Class.forName(“全类名”):将字节码文件加载进内存,返回class对象
(多用于配置文件,将类名定义在配置文件中)
2.类名.class:通过类名的属性class获取
(多用于参数传递)
3.对象.getClass():getClass()方法在object类中定义着
(多用于对象的获取字节码的方式)
Class对象功能:
-
获取功能
-
获取成员变量们
- Field[ ] getFields( )获取所有Public修饰的成员变量 。
- Field getField(String name) 获取Public修饰名称为name的成员变量。
- Field[ ] getDeclaredFields()获取所有的成员变量。
- Field getDeclaredField(String name)获取为name的成员变量,不用考虑修饰符。
获取到成员变量name后,有读取成员变量的值name.get(Object ),和设置成员变量的值name.set(Object,p)p为要设置的值。
(当成员修饰符为Private时,如果要使用set(),get()方法需要使用暴力反setAccessible(true))
-
获取构造方法
- Constructor[ ] getConstructors()获取所有Public修饰所有构造方法
- Constructor getConstructor()获取Public修饰构造方法,根据传入的参数选择匹配的构造方法
- Constructor[ ] getDeclaredConstructors()获取饰所有构造方法 。
- Constructor getConstructor()获取构造方法,根据传入的参数选择匹配的构造方法
获取到构造方法,不考虑修饰符
则可以用newInstance()创建对象(class对象中也有newInstance方法)
-
获取成员方法们
- Method [ ] getMethods( ) 获取所有Public修饰所有成员方法
- Method getMethod( String name )获取Public修饰成员方法,方法名为name
- Method [ ] getDeclaredMethods( )获取所有所有成员方法
- Method getDeclaredMethod( String name)获取成员方法,方法名为name,不需要考虑修饰符
获取到方法后,可以使用invoke(p,方法传入参数),也可以使用getName( )获取到方法名
-
获取类名
- String getName( )返回字符串,为类的全类名(包名+类名)
小案例:
需求:写一个“框架”,不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并执行其中任意方法
实现:
- 配置文件
- 反射
步骤:
- 将需要创建的对象的全类名和需要执行的定义在配置文件中
- 在程序中加载读取配置文件
- 使用反射技术来加载类文件进内存
- 创建对象
- 执行方法
创建一个类Person
package domain; public class Person { public void eat() { System.out.println("eat......"); } }
创建配置文件pro.properties
className=domain.Person methodName=eat
创建一个反射类,创建对象,即使用方法
package com.company; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.util.Properties; /* * 框架类 * */ public class ReflectTest { public static void main(String[] args) throws Exception{ //可以创建任意类的对象,可以执行任意方法 Properties pro =new Properties(); //加载配置文件 //获取class目录下的配置文件 ClassLoader classLoader= ReflectTest.class.getClassLoader(); InputStream is=classLoader.getResourceAsStream("pro.properties"); pro.load(is); /获取配置文件中定义的数据 String className= pro.getProperty("className"); // 加载类进内存 String methodName=pro.getProperty("methodName"); Class cls=Class.forName(className); Object obj=cls.newInstance(); Method method=cls.getDeclaredMethod(methodName); method.invoke(obj); } }
-