zoukankan      html  css  js  c++  java
  • Java反射的一些效率分析

    在很长的时间里,一直以为使用反射技术效率低,使用反射创建对象,效率不如Map。

    这样的认知,也导致一个问题,就是程序员畏惧使用反射解决问题,尤其是片面追求程序效率的开发人员,其实这种认知是不对的。

    实验数据结果有点令人意外: 

    创建对象耗时:class.newInstance  > new HashMap > new Object

    填充值耗时   :map.put > obj.setValue > field.set

    Map的创建和值填充,不一定最快,因为map初始化做太多事情了(Map有默认容量),在值填充的时候,需要创建Entity对象。

    反射效率慢,是因为Field对象通常以数组存储,算法涉及大量的数组遍历;其中,Field私有属性的暴力访问,也是极其耗时的一个步骤,最后才产生了慢的结果,

    针对特殊的业务,可以预先处理一部分的反射,将预处理过的Class、Field等对象缓存起来,使用反射可以达到与Map相当的效率,

    如果有条件,可以学习asm包,从字节码直接分析对象。

    以下以创建一百万个对象为例:

    package spring;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import com.alibaba.fastjson.JSONObject;
    import com.client.bean.Person;
    
    public class Test {
        public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
            {
                //在很长的时间里,一直以为map是快速的存储结构,实际测试下,反而是最慢的
                //(但是map支持无限制地填充数据,这一点优于bean对象,尤其是数据库结果的封装,用Map算法十分简洁)
                List<Map<String,Object>> l = new ArrayList<>();
                Map<String,Object> map;
                int cnt = 1000000;
                long start = System.nanoTime();
                while(cnt-->0){
                    map= new HashMap<>();
                    map.put("name", "xiaoming");
                    map.put("age", cnt);
                    map.put("name", "xiaoming");
                    map.put("age", cnt);
                    l.add(map);
                }
                long end = System.nanoTime();
                System.out.println(l.size());
                System.out.println(start);
                System.out.println(end);
                System.out.println(end-start);
            }
            {
                //阿里的JSON本质是Map,效率上稍微低于map,但是并不明显
                List<JSONObject> l = new ArrayList<>();
                JSONObject map;
                int cnt = 1000000;
                long start = System.nanoTime();
                while(cnt-->0){
                    map= new JSONObject();
                    map.put("name", "xiaoming");
                    map.put("age", cnt);
                    l.add(map);
                }
                long end = System.nanoTime();
                System.out.println(l.size());
                System.out.println(start);
                System.out.println(end);
                System.out.println(end-start);
            }
            {
                //使用bean对象
                List<Person> l = new ArrayList<>();
                Person map;
                int cnt = 1000000;
                long start = System.nanoTime();
                while(cnt-->0){
                    map= new Person();
                    map.setName("xiaoming");
                    map.setAge(cnt);
                    l.add(map);
                }
                long end = System.nanoTime();
                System.out.println(l.size());
                System.out.println(start);
                System.out.println(end);
                System.out.println(end-start);  
            }
            {   
                //对java反射进行优化,先解析一部分参数,如果用以下这种编码方式,它的效率是最快的
                //但是做map.get的时候,随着参数的增多,达到某个阶段,耗时会超过Bean的set函数
           //其中while循环下new Person()这一步,实际生产中,应该是class.newInstance(),这是极耗时的一步
    List<Person> l = new ArrayList<>(); Person map; int cnt = 1000000; Field fn = Person.class.getDeclaredField("name"); fn.setAccessible(true); Field fa = Person.class.getDeclaredField("age"); fa.setAccessible(true); Map<String,Field> f = new HashMap<>(); f.put("name", fn); f.put("age", fa); long start = System.nanoTime(); while(cnt-->0){ map= new Person(); f.get("name").set(map, "xiaoming"); f.get("age").set(map, cnt); l.add(map); } long end = System.nanoTime(); System.out.println(l.size()); System.out.println(start); System.out.println(end); System.out.println(end-start); } { //所有的反射留到使用时再解析,这种方式会随着参数变多, //耗时也越来越多,超过某个阶段,效率低于Map List<Person> l = new ArrayList<>(); Person map; int cnt = 1000000; long start = System.nanoTime(); Field fa,fn; while(cnt-->0){ fn = Person.class.getDeclaredField("name"); fn.setAccessible(true); fa = Person.class.getDeclaredField("age"); fa.setAccessible(true); map= new Person(); fn.set(map, "xiaoming"); fa.set(map, cnt); l.add(map); } long end = System.nanoTime(); System.out.println(l.size()); System.out.println(start); System.out.println(end); System.out.println(end-start); } } }
  • 相关阅读:
    java实现第五届蓝桥杯出栈次序
    java实现第五届蓝桥杯年龄巧合
    java实现第五届蓝桥杯年龄巧合
    java实现第五届蓝桥杯年龄巧合
    java实现第五届蓝桥杯年龄巧合
    java实现第五届蓝桥杯年龄巧合
    Java使用RandomAccessFile读写文件
    Java 实现文件随机读写-RandomAccessFile
    NIO 中文乱码自我解决的简单DEMO
    NIO 中文乱码问题的解决代码实现
  • 原文地址:https://www.cnblogs.com/chenss15060100790/p/10237751.html
Copyright © 2011-2022 走看看