探究java反射取值与方法取值性能对比
由于我开发框架时,经常需要对象取值。常用的取值方式有:
- 反射取值
- 方法调用取值
环境
同一台电脑:
jdk 21.0.2
idea 2023.3.3
1. 测试代码(常用)
1.1 反射取值
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
field();
System.out.println("耗时:" + (System.currentTimeMillis() - start));
}
private static List<Object> field() throws Exception {
TestParam param = new TestParam();
param.setA("a");
param.setB("b");
param.setC("c");
List<Object> list = new ArrayList<>(8000);
for (int i = 0; i < 5000; i++) {
Field field = TestParam.class.getDeclaredField("a");
field.setAccessible(true);
list.add(field.get(param));
}
return list;
}
1.2 方法调用
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
method();
System.out.println("耗时:" + (System.currentTimeMillis() - start));
}
private static List<Object> method() throws Exception {
TestParam param = new TestParam();
param.setA("a");
param.setB("b");
param.setC("c");
List<Object> list = new ArrayList<>(8000);
for (int i = 0; i < 5000; i++) {
Method method = TestParam.class.getMethod("getA");
list.add(method.invoke(param));
}
return list;
}
1.3 测试结果
耗时毫秒:
反射取值 | 12 | 11 | 11 | 12 | 12 | 12 |
---|---|---|---|---|---|---|
方法调用 | 14 | 15 | 16 | 16 | 15 | 15 |
不难看出,反射取值优胜
但是我们开发时,通常会把操作对象进行缓存,所以我们把
Method method = TestParam.class.getMethod("getA");
与 Field field = TestParam.class.getDeclaredField("a");
拿到for循环外,进行第二次测试。
2. 测试代码(缓存)
环境换成了笔记本
2.1 反射
public static void main(String[] args) throws Exception {
long end = 0L, start = System.currentTimeMillis();
for (int i = 0; i < 6; i++) {
List<Object> list = field();
end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start));
start = end;
}
}
private static List<Object> field() throws Exception {
TestParam param = new TestParam();
param.setA("a");
param.setB("b");
param.setC("c");
List<Object> list = new ArrayList<>(8000);
// 当做从缓存中拿
Field field = TestParam.class.getDeclaredField("a");
field.setAccessible(true); // 做了访问操作,因为是缓存,所以提前执行
for (int i = 0; i < 5000; i++) {
list.add(field.get(param));
}
return list;
}
结果
耗时:8
耗时:5
耗时:0
耗时:1
耗时:0
耗时:1
中途出现 0
不知道不知道是不是jvm优化
2.2 方法调用
public static void main(String[] args) throws Exception {
long end = 0L, start = System.currentTimeMillis();
for (int i = 0; i < 1; i++) {
List<Object> list = method();
end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start));
start = end;
}
}
private static List<Object> method() throws Exception {
TestParam param = new TestParam();
param.setA("a");
param.setB("b");
param.setC("c");
List<Object> list = new ArrayList<>(8000);
// 当做从缓存中拿
Method method = TestParam.class.getMethod("getA");
for (int i = 0; i < 5000; i++) {
list.add(method.invoke(param));
}
return list;
}
结果:
耗时:9
耗时:8
耗时:5
耗时:4
耗时:3
耗时:4
2.3 测试结果
上面的结果是挑选了比较好的数据,不难看出,即便是缓存,也是反射优胜
。
3. 结论
对象取值,预先缓存反射对象,将会获得更快的取值速度。推荐使用反射取值