运行环境
Windows 10 专业版 19044.1766
16GB DDR4 2667MHZ
Intel i5-10500 CPU@3.10GHz
JDK 1.8 181
文章内容
对比不同Java反射操作JavaBean的耗时。
JavaBean构成
public class Note {
private String content;
private String colorTag;
public Note() {
}
public String getContent() {
return this.content;
}
public String getColorTag() {
return this.colorTag;
}
public void setContent(String content) {
this.content = content;
}
public void setColorTag(String colorTag) {
this.colorTag = colorTag;
}
}
测试代码:
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Note note = new Note();
long startTime = System.currentTimeMillis();
String str = "ctx";
int count = 1;
int[] countArr = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
for (int j = 0; j < countArr.length; j++) {
count = countArr[j];
// 正常操作JavaBean的get/set方法
Note normalNote = new Note();
normalNote.setContent("1");
startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
normalNote = new Note();
normalNote.setContent(str + i);
}
System.out.println("normal count:" + count + ":" + (System.currentTimeMillis() - startTime));
// 通过反射操作JavaBean的get/set方法
Note gsNote = new Note();
gsNote.setContent("1");
startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
gsNote = new Note();
doSetter(gsNote, getSetter(Note.class, gsNote.getClass().getDeclaredField("content")), str + i);
}
System.out.println("get/set count:" + count + ":" + (System.currentTimeMillis() - startTime));
// setAccessible方式
Note accessNote = new Note();
accessNote.setContent("1");
startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
accessNote = new Note();
ReflectUtil.setFieldValue(accessNote, accessNote.getClass().getDeclaredField("content"), str + 1);
}
System.out.println("setAccessible count:" + count + ":" + (System.currentTimeMillis() - startTime));
}
}
结果:
设置值
循环次数 | 正常操作 | set方法反射 | setAccessible |
---|---|---|---|
1 | 0 | 4 | 51 |
10 | 0 | 0 | 0 |
100 | 0 | 2 | 1 |
1000 | 0 | 5 | 2 |
10000 | 1 | 20 | 7 |
100000 | 13 | 65 | 29 |
1000000 | 20 | 385 | 154 |
10000000 | 267 | 2965 | 880 |
100000000 | 2096 | 29681 | 8928 |
获取值
循环次数 | 正常操作 | get方法反射 | setAccessible |
---|---|---|---|
1 | 0 | 6 | 5 |
10 | 0 | 0 | 0 |
100 | 0 | 2 | 0 |
1000 | 0 | 7 | 1 |
10000 | 0 | 30 | 4 |
100000 | 2 | 115 | 20 |
1000000 | 2 | 884 | 70 |
10000000 | 0 | 7258 | 719 |
100000000 | 0 | 72805 | 7083 |
总结
- 直接操作对象的方法是最快的。
- 1000次内三种方式的耗时相差不大,1000次后的耗时差距开始出现明显的差距。
- 如果需要频繁的进行反射操作,使用setAccessible会更高效。
文章如有错误,还望各位大佬不吝指正。