03.反射
# 01.基本使用
动态加载类:运行时动态地加载需要使用的类
获取类的信息:获取类的构造函数、字段、方法等信息,包括访问修饰符、参数类型
创建对象:在运行时动态地创建类的实例
调用方法:在运行时动态地调用类的方法,包括公有方法、私有方法,以及静态方法等
访问和修改字段:可以在运行时动态地访问和修改类的字段,包括公有字段、私有字段等
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test{
public static void main(String[] args) throws
ClassNotFoundException, IllegalAccessException,
InstantiationException, NoSuchMethodException,
InvocationTargetException, NoSuchFieldException {
// 动态加载类
Class<?> clazz = Class.forName("cls.MyClass");
Object obj = clazz.getDeclaredConstructor().newInstance();
System.out.println(obj); // MyClass Instance
// 获取类的字段
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("Field: " + field.getName()); // Field: name
}
// 获取类的方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("Method: " + method.getName()); // Method: toString
}
// 获取类的方法
Method method = MyClass.class.getDeclaredMethod("setName", String.class);
// 调用方法
method.invoke(obj, "Tom");
// 获取类的字段
Field field = MyClass.class.getDeclaredField("name");
field.setAccessible(true); // 设置私有字段可访问
String name = (String) field.get(obj);
System.out.println("Name: " + name); // 输出:Name: Tom
}
}
class MyClass {
private String name;
@Override
public String toString() {
return "MyClass Instance";
}
public void setName(String name) {
this.name = name;
}
}
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 02.动态代理
├── Calculator.java
├── CalculatorImpl.java
├── LoggingHandler.java
└── Main.java
1
2
3
4
2
3
4
# 1、Main.java
- 测试类
Main
来演示如何使用动态代理创建Calculator
的代理对象,并且调用代理对象的方法
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
Calculator calculator = new CalculatorImpl();
// 创建了一个 Calculator 接口类型的代理对象 p
Calculator p = (Calculator) Proxy.newProxyInstance(
Calculator.class.getClassLoader(), // 获取了 Calculator 接口的类加载器,用于加载动态代理类
new Class[]{Calculator.class}, // 获取了 Calculator 接口的类加载器,用于加载动态代理类
new LoggingHandler(calculator) // 指定了代理对象要实现的接口,这里只有 Calculator 接口
);
int result1 = p.add(5, 3);
System.out.println("Result of addition: " + result1);
// Before method add
// After method add
// Result of addition: 8
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2、LoggingHandler.java
- 编写一个简单的动态代理类
LoggingHandler
- 它实现了
InvocationHandler
接口,用于在方法调用前后添加日志记录
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/*
定义LoggingHandler类,该类实现了 InvocationHandler 接口用于处理动态代理对象的方法调用
*/
public class LoggingHandler implements InvocationHandler {
// 声明了一个私有的 Object 类型成员变量 target,用于保存原始对象,即代理对象所代理的真实对象
private final Object target;
// LoggingHandler 类的构造函数,接收一个 Object 类型的参数 target
public LoggingHandler(Object target) {
this.target = target;
}
// invoke 方法的重写,该方法是 InvocationHandler 接口的核心方法,用于处理代理对象的方法调用
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method " + method.getName());
// 调用原始对象 target 的方法,并将传入的参数 args 传递给该方法
Object result = method.invoke(target, args);
System.out.println("After method " + method.getName());
return result;
}
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 3、Calculator.java 接口
- 定义一个接口
Calculator
,它包含了两个方法add
和subtract
public interface Calculator {
int add(int a, int b);
int subtract(int a, int b);
}
1
2
3
4
2
3
4
# 4、CalculatorImpl.java
- 创建一个实现了该接口的类
CalculatorImpl
,用于提供基本的计算功能
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int subtract(int a, int b) {
return a - b;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
上次更新: 2024/5/31 11:18:42