使用反射(java.lang.reflect.Field
get
和set
函数)设置和获取对象属性,而不是调用对象本身的set
和get
,导致任何显着的性能差异?
答案 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 - 似乎是说对get
或set
方法的反射调用比直接访问/更新字段慢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
似乎反射实际上更快。没想到这个...