Java 反射到底慢在哪?( 二 )

测试结果如下:

Java 反射到底慢在哪?

文章插图
 
反射性能测试结果
测试结论:
  • 反射的确会导致性能问题;推荐看下《Java反射是什么?》够了 。
  • 反射导致的性能问题是否严重跟使用的次数有关系 , 如果控制在100次以内 , 基本上没什么差别 , 如果调用次数超过了100次 , 性能差异会很明显;
  • 四种访问方式 , 直接访问实例的方式效率最高;其次是直接调用方法的方式 , 耗时约为直接调用实例的1.4倍;接着是通过反射访问实例的方式 , 耗时约为直接访问实例的3.75倍;最慢的是通过反射访问方法的方式 , 耗时约为直接访问实例的6.2倍;
反射到底慢在哪?跟踪源码可以发现 , 四个方法中都存在实例化ProgramMonkey的代码 , 所以可以排除是这句话导致的不同调用方式产生的性能差异;通过反射调用方法中调用了setAccessible方法 , 但该方法纯粹只是设置属性值 , 不会产生明显的性能差异;所以最有可能产生性能差异的只有getMethod和getDeclaredField、invoke和set方法了 , 下面分别就这两组方法进行测试 , 找到具体慢在哪?
首先测试invoke和set方法 , 修改getReflectCallMethodCostTime和getReflectCallFieldCostTime方法的代码如下:
    private long getReflectCallMethodCostTime(int count){        long startTime = System.currentTimeMillis();        ProgramMonkey programMonkey = new ProgramMonkey("小明", "男", 12);        Method setmLanguageMethod = null;        try{            setmLanguageMethod = programMonkey.getClass().getMethod("setmLanguage", String.class);            setmLanguageMethod.setAccessible(true);        }catch(NoSuchMethodException e){            e.printStackTrace();        }        for(int index = 0 ; index < count; index++){            try{                setmLanguageMethod.invoke(programMonkey, "Java");            }catch(IllegalAccessException e){                e.printStackTrace();            }catch(InvocationTargetException e){                e.printStackTrace();            }        }        return System.currentTimeMillis()-startTime;    }    private long getReflectCallFieldCostTime(int count){        long startTime = System.currentTimeMillis();        ProgramMonkey programMonkey = new ProgramMonkey("小明", "男", 12);        Field ageField = null;        try{            ageField = programMonkey.getClass().getDeclaredField("mLanguage");        }catch(NoSuchFieldException e){            e.printStackTrace();        }        for(int index = 0 ; index < count; index++){            try{                ageField.set(programMonkey, "Java");            }catch(IllegalAccessException e){                e.printStackTrace();            }        }        return System.currentTimeMillis()-startTime;    }


推荐阅读