反射
反射的概念
Java反射机制实在运行状态中,对于任何一个类,都能知道这个类的所有属性和方法。对于任意一个对象,都能调用它的任意方法和属性。
这种动态获取信息以及动态调用对象方法的功能被称为Java反射机制。
获取字节码对象的三种方式
//1.使用类名调用.class属性(.class不是只有类能调用)
Class c1 = String.class;
//2.使用一个类的对象调用.getClass()方法
Class c2 = "abd".getClass();
//3.使用Class类的静态方法forName("类全名")
Class c3 = Class.forName("java.lang.String");
System.out.println(c1 == c2);//true
System.out.println(c2 == c3);//true
反射操作构造方法
反射获取构造方法:
- getConstructor(Class… c) 可以获取某一个构造方法(公共的)
- getConstructors() 可以获取所有的构造方法(公共的)
反射执行构造方法
- newInstance(Object… obj) : 执行当前构造方法创建对象。(方法传递的参数是创建对象时的实际参数)
Class c1 = Class.forName("com.test.reflect.Student");
// 获取空参构造
Constructor con1 = c1.getConstructor();
// 获取有参构造
Constructor con2 = c1.getConstructor(String.class, int.class);
// 使用无参构造创建对象
Object o1 = con1.newInstance();
System.out.println(o1);
// 使用有参构造创建对象
Object o2 = con2.newInstance("张三", 21);
System.out.println(o2);
反射操作成员方法
反射获取成员方法
- getMethod(String name, Class… c) :获取一个成员方法(公共的)
String name 表示方法名称
Class… c 表示的是方法的参数的类型
反射执行成员方法
- Object invoke(Object obj , Object… o) :让方法执行
第一个参数表示执行的对象
第二个参数表示方法的实际参数
返回值表示方法的实际返回值
Class c1 = Class.forName("com.test.reflect.Student");
// 获取空参构造
Constructor con = c1.getConstructor();
// 通过构造方法创建对象
Object o = con.newInstance();
// 设置姓名方法
Method method1 = c1.getMethod("setName", String.class);
method1.invoke(o, "张三");
// 获取姓名方法
Method method2 = c1.getMethod("getName");
System.out.println(method2.invoke(o));// 输出张三
暴力反射
暴力反射的概念:
反射正常情况下遵从java权限修饰的规则。
如果使用暴力反射就可以打破权限修饰符的规则。
写法: 在所有的获取方法之间加declared词就可以了,然后调用setAccessable(true)就表示可以访问了。
// 通过暴力反射获取变量
private String name;
private int age;
// 私有化一个方法进行测试
private String getName() {
return name;
}
Class c1 = Class.forName("com.test.reflect.Student");
// 获取空参构造
Constructor con = c1.getConstructor();
// 通过构造方法创建对象
Object o = con.newInstance();
// 设置姓名方法
Method method1 = c1.getMethod("setName", String.class);
method1.invoke(o, "张三");
// 暴力反射获取被私有的方法
Method method2 = c1.getDeclaredMethod("getName");
// 设置为可以访问
method2.setAccessible(true);
System.out.println(method2.invoke(o));
// 暴力反射获取被私有的成员
Field name = c1.getDeclaredField("name");
System.out.println(name);
反射的应用场景
一般反射都是配合配置文件使用,这样我们修改一些参数的时候直接修改配置文件就可以了。
className=com.test.reflect.Student
methodName=getName
//Properties配置文件
Properties prop = new Properties();
//读取文件的键值对
prop.load(new FileReader("practice\\a.properties"));
//根据键获取值
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
Class c = Class.forName(className);
//字节码获取构造方法
Constructor con = c.getConstructor();
//创建对象
Object o = con.newInstance();
Method method1 = c.getMethod("setName", String.class);
method1.invoke(o, "张三");
//获取方法
Method m = c.getMethod(methodName);
//执行方法
System.out.println(m.invoke(o));