反射
Yu9

0x01 反射的作用

让java具有动态性

修改已有对象的属性

动态生成对象

动态调用方法

操作内部类和私有方法

java是一个强语言,比如一个字符串,常见出来时字符串类型,就改变不了了

1
String name="zahngsan";

通过反射的话我们就可以改变他

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

执行构造方法

获取成员属性 … 做一些操作

获取成员方法 … 做一些操作

image-20231018212937580

从原型class实例化对象

image-20231018213359511

image-20231018213410975

密码

image-20231018214109999

image-20231018215143312

通过set方法,修改他的属性值

image-20231018214340255

set方法需要传入两个参数

  • 第一个参数是修改谁的值,需要传入的是类的实例
  • 第二个参数是要改成的值

image-20231018214644183

image-20231018215236547

继续修改它的age值

image-20231018215621257

很尴尬,报错了(因为他是私有属性private)

image-20231018215710228

那么有办法解决吗? 嘿嘿,肯定有

image-20231018215909578

image-20231018215942973

image-20231018220010295

继续调用方法

由于person里边没有定义方法,我们先添加一个方法

image-20231018222021838

继续利用反射执行这个方法

image-20231018222144696

我们在执行构造方法的时候就指明了参数类型,这里我们没有指定类型,那他会不会识别。

运行看看,不出意外报错了

image-20231018222324061

所以我们要告诉他参数类型(如果是私有的我们还要setAccessible修改权限)

image-20231018222520850

image-20231018222532570

完整代码:

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的class
Person person = new Person();
Class c = person.getClass();

//从原型class实例化对象
/*

//无参构造
c.newInstance();

*/

//有参构造
Constructor personconstructor = c.getConstructor(String.class, int.class);
Person p = (Person) personconstructor.newInstance("qwe", 24);

//获取类中的属性name
Field nameFile = c.getField("name");
// System.out.println(nameFile);

//修改属性
nameFile.set(p,"asd");
//System.out.println(p);

//获取类中的属性age
Field ageFile = c.getDeclaredField("age");
//修改权限
ageFile.setAccessible(true);
ageFile.set(p,18);
// System.out.println(p);

//获取方法
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");
由 Hexo 驱动 & 主题 Keep
总字数 50.7k 访客数 访问量