10

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

4

3 回答 3

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,没有设置可访问标志。设置它会使比率下降到 83。

于 2012-10-21T08:08:09.500 回答
0

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

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

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

于 2012-10-21T08:28:25.623 回答
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 和我的电脑上):

2714
2741
2625

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

于 2020-04-14T19:15:51.430 回答