设置和获取使用反射的性能

时间:2012-10-21 08:05:44

标签: java reflection

使用反射(java.lang.reflect.Field getset函数)设置和获取对象属性,而不是调用对象本身的setget ,导致任何显着的性能差异?

3 个答案:

答案 0 :(得分:6)

是的,基准测试很容易在15分钟内完成。

生成的代码更好,即使你缓存了反射访问器,我也试过了。

这是Java 7 64位:

import java.lang.reflect.Field;

class Data {
   public double _value;
   public double getValue()               { return _value; }
   public void   setValue( double value ) { _value = value; }
}

public class Reflect {
   public static final int LOOP_COUNT = 100_000_000;
   public static void main( String[] args ) throws Throwable {
      Data d = new Data();
      long start = System.currentTimeMillis();
      for( int i = 0; i < LOOP_COUNT; ++i ) {
         d.setValue( i );
      }
      System.err.println( System.currentTimeMillis() - start );
      Field field = Data.class.getDeclaredField( "_value" );
      start = System.currentTimeMillis();
      for( int i = 0; i < LOOP_COUNT; ++i ) {
         field.set( d, new Double( i ));
      }
      System.err.println( System.currentTimeMillis() - start );

      field.setAccessible( true ); // Optimization
      start = System.currentTimeMillis();
      for( int i = 0; i < LOOP_COUNT; ++i ) {
         field.set( d, new Double( i ));
      }
      System.err.println( System.currentTimeMillis() - start );
   }
}

结果:

20
37381
1677

比率接近1870 w / o可访问标志设置。设置它使比率下降到83。

答案 1 :(得分:0)

是的,它确实会产生显着的性能差异,并且网上有很多基准测试结果可以支持这一点。

例如:http://www.cowtowncoder.com/blog/archives/2007/02/entry_32.html - 似乎是说对getset方法的反射调用比直接访问/更新字段慢50倍。 (使用Field方法获取/设置的速度较慢。)

现在这些结果相当陈旧,并且(显然)在最近的HotSpot JVM中改进了反射的性能。即便如此,粗略的经验法则是“一个数量级或更多更慢”。

答案 2 :(得分:0)

我运行了一个稍作修改的版本:

public class Test {

    private static class Data {

        public double _value;

        public void setValue(double value) {
            _value = value;
        }
    }

    public static final int LOOP_COUNT = 100_000_000;

    public static void main(String[] args) throws Throwable {

        Data d = new Data();

        Random testing = new Random(5);
        long start = System.currentTimeMillis();
        for (int i = 0; i < LOOP_COUNT; ++i) {
            d.setValue(testing.nextDouble());
        }
        System.err.println(System.currentTimeMillis() - start);

        Field field = Data.class.getDeclaredField("_value");

        testing = new Random(5);
        start = System.currentTimeMillis();
        for (int i = 0; i < LOOP_COUNT; ++i) {
            field.setDouble(d, testing.nextDouble());
        }
        System.err.println(System.currentTimeMillis() - start);

        testing = new Random(5);
        field.setAccessible(true); // Optimization
        start = System.currentTimeMillis();
        for (int i = 0; i < LOOP_COUNT; ++i) {
            field.setDouble(d, testing.nextDouble());
        }
        System.err.println(System.currentTimeMillis() - start);
    }
}

结果(在Java 1.8.0_121和我的PC上):

2714
2741
2625

似乎反射实际上更快。没想到这个...