zoukankan      html  css  js  c++  java
  • 反射性能研究,反射赋值与set方法赋值对比

    可能我们有一个模糊的概念,反射性能会慢,但是有多慢没有一个具体的数据。那我就写代码来测试一下。

    package com.itbac.reflection;
    
    import java.lang.reflect.Field;
    
    public class test {
        public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
            long begin = System.currentTimeMillis();
            Book book = new Book();
            book.setName("java从入门到放弃");
            book.setNum(1);
            book.setPrice(1.2);
            System.out.println(book.toString());
                  //循环一千万次
            for (int i = 0; i < 10000000; i++) {
                //1.set方法赋值  耗时毫秒:7
    //            book.setNum(++i);
    
                //2.反射赋值  耗时毫秒:1045
                setFeild(book, i,"num");
            }
            System.out.println(book.toString());
            long end = System.currentTimeMillis();
            System.out.println("毫秒:"+(end-begin));
        }
    
        private static void setFeild(Book book, int i,String str) throws NoSuchFieldException, IllegalAccessException {
            Class<? extends Book> aClass = book.getClass();
            Field num = aClass.getDeclaredField(str);
            num.setAccessible(true);
            num.set(book, i);
        }
    }

    通过上面的测试,我发现在循环赋值一千万次的时候,反射耗时一秒。这个慢才能被人所感知。如果你的反射调用,少于一千万次,请不要说反射慢。

    再看两个方法的对比,set方法直接就能赋值,反射方法还需要获取Class 和 Field ,设置访问权限,好几部操作。我可以用一个map来优化一下。

    package com.itbac.reflection;
    
    import java.lang.reflect.Field;
    import java.util.HashMap;
    import java.util.Map;
    
    public class test {
        public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
            long begin = System.currentTimeMillis();
            Book book = new Book();
            book.setName("java从入门到放弃");
            book.setNum(1);
            book.setPrice(1.2);
            System.out.println(book.toString());
            Map<String, Field> map = new HashMap<>();
                  //循环一千万次
            for (int i = 0; i < 10000000; i++) {
                //1.set方法赋值  耗时毫秒:7
    //            book.setNum(++i);
    
                //2.反射赋值(没有用map)  耗时毫秒:1045
                //3.反射赋值(使用map缓存Field)  耗时毫秒:95
                setFeild(book, i,"num",map);
            }
            System.out.println(book.toString());
            long end = System.currentTimeMillis();
            System.out.println("耗时毫秒:"+(end-begin));
        }
    
        private static void setFeild(Book book, int i,String str,Map<String, Field> map) throws NoSuchFieldException, IllegalAccessException {
            Field field = map.get(str);
            if (null == field) {
                Class<? extends Book> aClass = book.getClass();
                field= aClass.getDeclaredField(str);
                field.setAccessible(true);
                map.put(str, field);
            }
            field.set(book, i);
        }
    }

    这样处理,得出一个数据,95 除以 7  约等于 13.5  ,得出结论,在一千万次调用,反射赋值比直接赋值慢了 13.5倍。

    但是,反射赋值一千万次,才耗时95毫秒,是人无法感知的速度。是可以被我们接受的程序代码运行速度。

    我试着提高反射的次数,看看多少次,才能被我们感觉到慢呢。

    代码运行结果如下:

    一亿次反射赋值,耗时毫秒:687

    两亿次反射赋值,耗时毫秒:1468

    个人的结论:

      反射赋值是比直接赋值慢,但是你在一亿次调用以内,你是感觉不到它慢的,可以放心使用。

    当然,set方法赋值更变态,2亿次赋值,耗时15毫秒。所以能不用反射,就尽量不用反射,实在不行,用也是可以的。

  • 相关阅读:
    linux 免交互状态下修改用户密码
    Sqlmap基础(一)
    cmd命令行指定系统延迟关机时间
    Shell 是个什么玩意
    Linux Shell脚本入门:tee命令
    shell脚本 -d 是目录文件,那么-e,-f等说明
    修改linux终端命令行颜色
    Linux 动画显示
    OpenVAS漏洞扫描基础教程之OpenVAS概述及安装及配置OpenVAS服务
    Curl命令使用
  • 原文地址:https://www.cnblogs.com/itbac/p/11963086.html
Copyright © 2011-2022 走看看