Java——反射三种方式的效率对比

转载自:https://blog.csdn.net/aitcax/article/details/52694423

1 使用field(效率最高)
            long start = System.nanoTime();
            Field[] fields = CallCount.class.getDeclaredFields();
            for (String str : dateList) {
                boolean exist = false;
                for (Field field : fields){
                    field.setAccessible(true);
                    if (field.getName().endsWith(str)) {
                        int value = 0;
                        for (CallCount callCount : callCountList) {
                            value += (Integer)field.get(callCount);
                        }
                        resultList.add(value);
                        exist = true;
                        break;
                    }
                }
                if (!exist) {
                    resultList.add(0);
                }
            }
            long end = System.nanoTime();
            log.info("old call cost :" + (end-start));

2 使用 org.apache.commons.beanutils.BeanUtils来获取属性
            long start = System.nanoTime();
            for (String str : dateList) {
                Integer value = getMinuteAccessCount(str, callCountList);
                resultList.add(value);
            }
            long end = System.nanoTime();
            log.info("new call cost :" + (end-start));

        private Integer getMinuteAccessCount(String minute, List<CallCount> callCountList) {
        Integer result = 0;
        String propertyName = "logMinute" + minute;
        for (CallCount callCount : callCountList) {
            int value = 0;
            try {
                value = Integer.valueOf(BeanUtils.getProperty(callCount, propertyName));
            } catch (NumberFormatException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                e.printStackTrace();
            }
            result += value;
        }
        return result;
    }

3  使用java.lang.reflect.Method获取值
 
 
            long start = System.nanoTime();
            for (String str : dateList) {
                Integer value = getMinuteAccessCount(str, callCountList);
                resultList.add(value);
            }
            long end = System.nanoTime();
            log.info("new call cost :" + (end-start));

        private Integer getMinuteAccessCount(String minute, List<CallCount> callCountList) {
        Integer result = 0;
        for (CallCount callCount : callCountList) {
            int value = 0;
            try {
                Method method = callCount.getClass().getDeclaredMethod("getLogMinute"+minute);
                Object obj = method.invoke(callCount);
                value = (Integer)obj;
            } catch (NumberFormatException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                e.printStackTrace();
            }
            result += value;
        }
        return result;
    }

4 耗时对比,在使用相同的查询条件,相同的数据的情况下。通过实验得到以下两组数据(耗时/纳秒)

1 old call cost :517599
1 old call cost :347916
1 old call cost :337312
1 old call cost :177893
1 old call cost :131709
1 old call cost :82789
1 old call cost :63973
3 new call cost :925383
3 new call cost :794016
3 new call cost :912382
 
1 old call cost :755016
1 old call cost :365364
1 old call cost :231944
1 old call cost :123498
1 old call cost :103315
1 old call cost :92025
1 old call cost :81762
2 new call cost :139741338
2 new call cost :3387140
2 new call cost :2230497
2 new call cost :9215854
2 new call cost :2313970
2 new call cost :1549374
2 new call cost :1884291
2 new call cost :1100880
2 new call cost :1488138
每组数据前的数字代表之前取值的方式。
由数据对比可以看出,耗时最小的,始终是方式1,并且方式1在多次调用时,耗时是逐步减少的,可能是有缓存机制。
耗时第二少的是方式3,耗时最多的是方式2.

5 解析

方式1,采用了最基本的java反射方式,使用Filed,循环bean的Field,得到Object,再转换为Integer类型。
方式2,采用了看似最简洁的BeanUitls,根据属性名,获取属性值。这样最耗时。
方式3,采用了获取bean的Method,然后invoke的方式来获取值。
---------------------
作者:aitcax
来源:CSDN
原文:https://blog.csdn.net/aitcax/article/details/52694423
原文地址:https://www.cnblogs.com/it-mh/p/11268317.html