探究java反射取值与方法取值性能对比

探究java反射取值与方法取值性能对比

由于我开发框架时,经常需要对象取值。常用的取值方式有:

  • 反射取值
  • 方法调用取值

环境

同一台电脑:

jdk 21.0.2 idea 2023.3.3

1. 测试代码(常用)

1.1 反射取值

java 复制代码
    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 方法调用

java 复制代码
    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 反射

java 复制代码
    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;
    }

结果

html 复制代码
耗时:8
耗时:5
耗时:0
耗时:1
耗时:0
耗时:1

中途出现 0 不知道不知道是不是jvm优化

2.2 方法调用

java 复制代码
    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;
    }

结果:

html 复制代码
耗时:9
耗时:8
耗时:5
耗时:4
耗时:3
耗时:4

2.3 测试结果

上面的结果是挑选了比较好的数据,不难看出,即便是缓存,也是反射优胜

3. 结论

对象取值,预先缓存反射对象,将会获得更快的取值速度。推荐使用反射取值

相关推荐
考虑考虑3 小时前
Jpa使用union all
java·spring boot·后端
用户3721574261354 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊5 小时前
Java学习第22天 - 云原生与容器化
java
渣哥6 小时前
原来 Java 里线程安全集合有这么多种
java
间彧7 小时前
Spring Boot集成Spring Security完整指南
java
间彧7 小时前
Spring Secutiy基本原理及工作流程
java
Java水解8 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆10 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学11 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole11 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端