注:本专栏文章均为本人原创,未经本人授权请勿私自转载,谢谢。
反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
以下是测试反射性能的示例代码,由于一般在使用反射的场合中基本都是将反射类缓存的(例如 Spring 中的 singletonMap 等),所以我们没有将实例化的过程参与计时:
public class MyApplication {
@Data
static class Human {
private Long id;
private String name;
private String gender;
private void run() {
//System.out.println("Human run");
}
private void eat() {
//System.out.println("Human eat");
}
}
public static void main(String[] args) throws Exception {
// 设定总执行次数
final int EXECUTE_COUNT = 1000000;
// new 方式执行
Human human = new Human();
long startTime = System.currentTimeMillis(); // 开始计时
for (int i = 0; i < EXECUTE_COUNT; i++) {
human.run();
human.eat();
}
System.out.println("New 方法耗时:" + (System.currentTimeMillis() - startTime));
// 反射方式执行
Class<?> aClass = Class.forName("com.example.demo.MyApplication$Human");
Object obj = aClass.newInstance();
Method runMethod = aClass.getDeclaredMethod("run");
runMethod.setAccessible(true);
Method eatMethod = aClass.getDeclaredMethod("eat");
eatMethod.setAccessible(true);
startTime = System.currentTimeMillis(); // 开始计时
for (int i = 0; i < EXECUTE_COUNT; i++) {
runMethod.invoke(obj);
eatMethod.invoke(obj);
}
System.out.println("反射方法耗时:" + (System.currentTimeMillis() - startTime));
}
}
# 以上程序输出:
New 方法耗时:9
反射方法耗时:15
# 若将创建逻辑移入 for 循环:
New 方法耗时:12
反射方法耗时:1273
可以看到,在动态创建对象时,反射确实带来了一些效率问题,但若将反射实例缓存后,两者性能差异并不大。而且这是执行了上百万次的运行时间,实际的生产中还需加入业务代码的执行时间,着电性能的差异就更显得微不足道了。
所以说,反射在动态创建对象时,会有较大的性能影响,解决方法就是将反射实例缓存。