反射:框架设计的灵魂
*框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
其实,用框架并不一定用得到反射。但是,如果你要开发一套框架供别人使用,就得用到反射。但是,如果我们知道了反射机制,就能在使用框架时游刃有余。
*反射:将类的各个组成部分封装为其他对象,这就是反射机制。
例如:将成员变量封装为Field对象;构造函数-->Constructor对象;成员方法-->Method对象
*获取class对象的方式:
1.Class.forName("全类名");将字节码文件加载进内存,返回Class对象(对应源代码阶段)*多用于配置文件,将类名定义在配置文件中,返回class对象
2.类名.class:通过类名的属性class获取(对应class类对象阶段)*多用于参数的传递
3.对象.getClass():getClass()方法在Object类中定义着 *多用于对象的获取字节码的方式
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的class对象都是同一个。

好处:1.可以在程序的运行过程中去操作这些对象。例如,String str 这个对象创建之后,str. 后会提示很多方法。这些方法其实就是str对象加载到内存之后,程序运行中程序提供的操作这些对象的方式。
/*Class对象功能:
*获取功能:
1.获取成员变量们:
*Field[] getFields();---获取所有public 修饰的成员变量
*Field getField(String name)----获取指定名称的public修饰的成员变量
*Field[] getDeclaredFields()----获取所有成员边浪
*Field getDeclaredField(String name)
*
*操作:
*1.设置值 2.获取值
*2.获取构造方法们
*Constructor<> getConstructors()
*Constructor<> getConstructor(类<>..parameterTypes)
*Constructor<> getDeclaredConstructor(类<>..parameterTypes)
*Constructor<>[] getDeclaredConstructor()
*
*3.获取成员方法们:
*Method[] getMethods()
*Method getMethod(String name,类<>...parameterTypes)
*Method[] getDeclaredMethods()
*Method getDeclaredMethod(String name,类<>..parameterTypes)
*
*4.获取类名
*String getName()
*/
2.可以解耦。来达到程序的可扩展性。
package cn.itcast.junit; import java.text.DateFormat.Field; public class ReflectDemo { public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { //获取Person的class对象 Class personClass=Person.class; /*1.获取成员变量们: *Field[] getFields(); *Field getField(String name) *Field[] getDeclaredFields() *Field getDeclaredField(String name) **/ //1.Field[] getFields();---获取所有public 修饰的成员变量 java.lang.reflect.Field[] Feilds=personClass.getFields(); for(java.lang.reflect.Field filed:Feilds){ System.out.println(filed); //public java.lang.String cn.itcast.junit.Person.a } //*Field getField(String name)----获取指定名称的public修饰的成员变量 Person p=new Person();
、 //Field 是对象 。对象就有方法。通过对象的方法完成操作。具体操作参见API文档 java.lang.reflect.Field f=personClass.getField("a");
、 //此时 f 为获取的 person 类中的String a 参数。如下对 f 进行设置值与赋值 f.set(p, "这是通过设置成员方法设置的值");//操作成员变量---设置成员变量的值 Object value=f.get(p); System.out.println(value); //*Field[] getDeclaredFields() System.out.println("\n================="); java.lang.reflect.Field[] filed = personClass.getDeclaredFields(); for(java.lang.reflect.Field f1:filed){ System.out.println(f1); } //*Field getDeclaredField(String name) //这里不能访问 d java.lang.reflect.Field f3=personClass.getDeclaredField("d"); Person p2=new Person(); //会报错 //f3.set(p2, "这是通过获取成员变量而设置的值"); //System.out.println(f3.get(p2)); //访问前忽略权限修饰符的安全检查---"暴力反射" f3.setAccessible(true); f3.set(p2, "这是暴力反射后获取成员变量而设置的值"); System.out.println(f3.get(p2)); } }
案例:
*需求:写一个“框架”,可以帮我们创建任意类的对象,并且执行其中任意的方法(在不改变该类的任何代码的前提下)。
*实现:
1.配置文件 2.反射
*步骤
1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
2.在程序中加载读取配置
3.使用反射技术来加载类文件进内存
4.创建对象
5.执行方法
文件列表+配置文件:(实现在不改变任何源代码的前提下,通过改变配置文件来达到获取不同类下的不同方法,并执行)


package cn.itcast.reflection;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
import org.omg.CORBA.portable.InputStream;
/*
* 框架类
* */
public class ReflectTest {
//可以创建任意类的对象,可以执行任意方法
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
/*前提:不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法*/
//1.加载配置文件
//1.1 创建Properties对象
Properties pro =new Properties();
//1.2加载配置文件,转换为一个集合
//1.2.1 获取文件class目录下的配置文件
ClassLoader classLoader=ReflectTest.class.getClassLoader();
java.io.InputStream is=classLoader.getResourceAsStream("pro.properties");
System.out.println(is);
pro.load(is);
//2.获取配置文件中配置的数据
String className=pro.getProperty("className");
//System.out.println(className);
String methodName=pro.getProperty("methodName");
//System.out.println(methodName);
//3.加载该类进内存
Class cls=Class.forName(className);
//创建对象
Object obj=cls.newInstance();
//System.out.println(obj);
//获取方法对象
Method method=cls.getMethod(methodName);
//执行方法
method.invoke(obj);
}
}

浙公网安备 33010602011771号