0x01 反射的作用
让java具有动态性
修改已有对象的属性
动态生成对象
动态调用方法
操作内部类和私有方法
java是一个强语言,比如一个字符串,常见出来时字符串类型,就改变不了了
通过反射的话我们就可以改变他
0x02 简单案例
通俗的理解一下:反射就是操作class,通过得到其class然后做出一些操作
以person类为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import java.io.Serializable;
public class Person implements Serializable { public String name; private int age;
public Person() { }
public Person(String name, int age) { this.name = name; this.age = age; }
public String toString() { return "Person{name = " + name + ", age = " + age + "}"; } }
|
获取原型class
执行构造方法
获取成员属性 … 做一些操作
获取成员方法 … 做一些操作
从原型class实例化对象
密码
通过set方法,修改他的属性值
set方法需要传入两个参数
- 第一个参数是修改谁的值,需要传入的是类的实例
- 第二个参数是要改成的值
继续修改它的age值
很尴尬,报错了(因为他是私有属性private)
那么有办法解决吗? 嘿嘿,肯定有
继续调用方法
由于person里边没有定义方法,我们先添加一个方法
继续利用反射执行这个方法
我们在执行构造方法的时候就指明了参数类型,这里我们没有指定类型,那他会不会识别。
运行看看,不出意外报错了
所以我们要告诉他参数类型(如果是私有的我们还要setAccessible修改权限)
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| Person person = new Person(); Class c = person.getClass();
Constructor personconstructor = c.getConstructor(String.class, int.class); Person p = (Person) personconstructor.newInstance("qwe", 24);
Field nameFile = c.getField("name");
nameFile.set(p,"asd");
Field ageFile = c.getDeclaredField("age");
ageFile.setAccessible(true); ageFile.set(p,18);
Method eat = c.getMethod("eat",String.class);
eat.invoke(p,"炸鸡");
|
0x03 Runtime
01、正常执行
1
| Runtime.getRuntime().exec("calc.exe");
|
02、反射调用(调用静态方法getRunti实例me获得Runtime实例)
1 2 3 4 5 6 7
| Class clazz = Class.forName("java.lang.Runtime");
Method exec = clazz.getMethod("exec", String.class);
Object getRuntime = clazz.getMethod("getRuntime").invoke(clazz);
exec.invoke(getRuntime,"calc.exe");
|
03、反射(获取私有构造方法实例化Runtime)
1 2 3 4 5 6 7 8
| Class clazz = Class.forName("java.lang.Runtime");
Method exec = clazz.getMethod("exec", String.class);
Constructor m = clazz.getDeclaredConstructor(); m.setAccessible(true);
exec.invoke(m.newInstance(), "calc.exe");
|