反射相关使用和暴破
通过反射创建对象
- 方式一:调用类中的public修饰的无参构造器;
- 方式二:调用类中的指定构造器;
- Class类相关方法:
- newInstance():调用类中的无参构造器,获取对应类的对象;
- getConstructor(Class...clazz):根据参数列表,获取对应的public构造器对象;
- getDecalaredConstructor(Class...clazz):根据参数列表,获取对应的所有构造器对象;
- Constructor类相关方法:
- setAccessible():暴破;
- newInstance(Object...obj):调用构造器;
代码演示:- package com.hspedu.reflection;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- /**
- * @author: 86199
- * @date: 2023/6/5 20:32
- * @description: 演示通过反射机制创建实例
- */
- public class ReflectCreateInstance {
- public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
- //先获取User类的Class对象
- Class<?> userClass = Class.forName("com.hspedu.reflection.User");
- //1. 通过public无参构造器构造实例
- Object user = userClass.newInstance();
- System.out.println("user = " + user);
- //2. 通过public有参构造器构造实例
- /*
- 此时 constructor 对象就是这个构造器
- public User(String name){//public 的有参构造器
- this.name = name;
- }
- */
- //先得到对应的构造器
- Constructor<?> constructor = userClass.getConstructor(String.class);
- //创建实例,传入实参
- Object user1 = constructor.newInstance("小花");
- System.out.println("user1 = " + user1);
- //3. 通过非public有参构造器构造实例
- //先得到对应的private构造器
- Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class, int.class);
- //创建实例
- declaredConstructor.setAccessible(true);//暴破【暴力破解】,使用反射可以访问private构造器/方法/属性,反射面前,都是纸老虎
- Object user2 = declaredConstructor.newInstance("小黑", 20);
- System.out.println("user2 = " + user2);
- }
- }
- class User{//User类
- //属性
- private String name = "大黄";
- private int age = 10;
- public User() {//无参构造器
- }
- public User(String name){//public 的有参构造器
- this.name = name;
- }
- private User(String name, int age) {//private 有参构造器
- this.name = name;
- this.age = age;
- }
- @Override
- public String toString() {
- return "User [ age = " + age + ", name = " + name + " ]";
- }
- }
- /*运行结果
- user = User [ age = 10, name = 大黄 ]
- user1 = User [ age = 10, name = 小花 ]
- user2 = User [ age = 20, name = 小黑 ]
- */
复制代码 通过反射访问类中成员
访问属性
- 根据属性名获取Field对象
Field f = clazz对象.getDeclaredField(属性名);//获取所有
Field f = clazz对象.getField(属性名);//获取公有
- 暴破:f.setAccessible(true)//f 是Field
- 访问
- f.set(o, 值) //o 表示本类的对象
- System.out.println(f.get(o));//o 表示对象
复制代码 - 注意:如果是静态属性,则set和get中的参数o,可以写成null;
代码演示:- package com.hspedu.reflection;
- import java.lang.reflect.Field;
- /**
- * @author: 86199
- * @date: 2023/6/5 21:37
- * @description: 演示反射操作属性
- */
- public class ReflectAccessProperty {
- public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
- //得到Student类对应的Class对象
- Class<?> stuClass = Class.forName("com.hspedu.reflection.Student");
- //创建对象
- Object o = stuClass.newInstance();//o 的运行类型就是Student
- System.out.println(o.getClass());//class com.hspedu.reflection.Student
- //1. 使用反射得到age属性对象
- Field age = stuClass.getField("age");//拿到公有的
- age.set(o, 88);//通过反射操作属性
- System.out.println(o);
- System.out.println(age.get(o));//返回age的值
- //2. 使用反射操作name属性
- Field name = stuClass.getDeclaredField("name");
- name.setAccessible(true);//对name进行暴破,可以操作私有属性
- //name.set(o, "大黑");
- name.set(null, "大白");//因为name是static修饰的,所以这里 o 也可以写成 null
- System.out.println(o);
- System.out.println(name.get(o));//获取属性值
- System.out.println(name.get(null));//只有静态的才能这样用
- }
- }
- class Student{//类
- public int age;
- private static String name;
- public Student() {
- }
- @Override
- public String toString() {
- return "Student [ " +
- "age = " + age + " name = " + name +
- ']';
- }
- }
- /* 运行结果
- class com.hspedu.reflection.Student
- Student [ age = 88 name = null]
- 88
- Student [ age = 88 name = 大白]
- 大白
- 大白
- */
复制代码 访问方法
- 根据方法名和参数列表获取Method方法对象:
Method m = clazz.getDeclaredMethod(方法名, XX.class);//得到本类的所有方法
Method m = clazz.getMethod(方法名, XX.class);//得到本类的public方法
- 暴破:m.setAccessible(true);
- 访问:Object returnVal = m.invoke(o, 实参列表);//o就是本类的对象
- 注意:如果是静态方法,则invoke的参数o,可以写成null;
代码演示:- package com.hspedu.reflection;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- /**
- * @author: 86199
- * @date: 2023/6/5 21:56
- * @description: 演示通过反射调用方法
- */
- public class ReflectAccessMethod {
- public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException {
- //获取Boss类的Class对象
- Class<?> bossCls = Class.forName("com.hspedu.reflection.Boss");
- //创建对象
- Object o = bossCls.newInstance();
- //1. 调用public 的 hi 方法
- //得到hi方法对象
- // Method hi = bossCls.getMethod("hi", String.class);//OK
- Method hi = bossCls.getDeclaredMethod("hi", String.class);//OK
- hi.invoke(o, "大黄!");
- //2. 调用private的say方法
- //得到say方法对象
- Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
- //因为say方法私有,所以需要先暴破
- say.setAccessible(true);
- System.out.println(say.invoke(o, 20, "张三", '男'));
- //3. 因为say方法是static,所以可以这样调用
- System.out.println(say.invoke(null, 18, "李四", '女'));
- //返回值,在反射中如果方法有返回值统统返回Object,但是运行类型和方法定义的返回类型相同
- //如果返回类型是void,返回null也是Object类型
- Object reVal = say.invoke(null, 23, "王五", '男');
- System.out.println("reVal的运行类型" + reVal.getClass());
- }
- }
- class Boss{//类
- public int age;
- private static String name;
- public Boss() {//构造器
- }
- private static String say(int n, String s, char c){//静态方法
- return n + " " + s + " " + c;
- }
- public void hi(String s){//普通方法
- System.out.println("hi " + s);
- }
- }
- /* 运行结果
- hi 大黄!
- 20 张三 男
- 18 李四 女
- reVal的运行类型class java.lang.String
- */
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |