我试图在反射性能特征上找到某种确定的答案。在除非你必须“不要使用它”之外,没有什么是真正具体的。也许这没关系,因为用例决定了反射程序运行的好坏程度。
我放手了但是我读过几篇文章,这些文章表明Java 6的反射例程几乎和其他例程一样快,特别是如果你使用-server开关。
我根本没有看到这一点。我在Mac 10.8.4上使用Java 6.
看看我的日常生活。我只使用随机的东西,所以希望编译器/运行时不会以某种方式优化文字。我已经让我的for循环运行了很长时间,我总是得到直接例程大约13-15毫秒的值和反射例程大约590-595毫秒。
import java.lang.reflect.Field;
import java.util.Random;
public class Reflection {
static final int ITERATIONS = 100000;
static final String[] STRINGS = { "asdf", "qwer", "dfgh", "scvb", "ertyerty" };
static final Random random = new Random( System.currentTimeMillis() );
public static void main( String[] args ) throws Exception {
for ( int i = 0; true; i++ ) {
System.out.println( "i=" + i + ", direct=" + testDirectCallSpeed() + ", reflective=" + testReflectiveCallSpeed() );
}
}
static class Blah {
String a, b, c, d, e, f;
int g, h, i, j, k, l;
public String toString() {
StringBuilder sb = new StringBuilder( 100 );
sb.append( super.toString() );
sb.append( ", a=" ).append( a );
sb.append( ", b=" ).append( b );
sb.append( ", c=" ).append( c );
sb.append( ", d=" ).append( d );
sb.append( ", e=" ).append( e );
sb.append( ", f=" ).append( f );
sb.append( ", g=" ).append( g );
sb.append( ", h=" ).append( h );
sb.append( ", i=" ).append( i );
sb.append( ", j=" ).append( j );
sb.append( ", k=" ).append( k );
sb.append( ", l=" ).append( l );
return sb.toString();
}
}
public static long testDirectCallSpeed() {
System.gc();
Blah[] blahs = new Blah[ ITERATIONS ];
long begin = System.currentTimeMillis();
Blah blah;
for ( int i = 0; i < ITERATIONS; i++ ) {
blah = new Blah();
blah.a = getString();
blah.b = getString();
blah.c = getString();
blah.d = getString();
blah.e = getString();
blah.f = getString();
blah.g = getInt();
blah.h = getInt();
blah.i = getInt();
blah.j = getInt();
blah.k = getInt();
blah.l = getInt();
blahs[ i ] = blah;
}
printRandomBlah( blahs );
return System.currentTimeMillis() - begin;
}
public static long testReflectiveCallSpeed() throws Exception {
System.gc();
Blah[] blahs = new Blah[ ITERATIONS ];
long begin = System.currentTimeMillis();
Blah blah;
Class<?> type;
for ( int i = 0; i < ITERATIONS; i++ ) {
blah = new Blah();
for ( Field f : Blah.class.getDeclaredFields() ) {
type = f.getType();
if ( String.class == type ) f.set( blah, getString() );
else if ( int.class == type ) f.setInt( blah, getInt() );
}
blahs[ i ] = blah;
}
printRandomBlah( blahs );
return System.currentTimeMillis() - begin;
}
public static void printRandomBlah( Blah[] blahs ) {
// System.out.println( blahs[ random.nextInt( blahs.length ) ] );
}
public static int getInt() { return random.nextInt(); }
public static String getString() { return STRINGS[ random.nextInt( STRINGS.length ) ]; }
}
答案 0 :(得分:1)
如果你在“testReflectiveCall”的东西中提取所有没有真正调用setter的东西,那几乎是一个不可估量的差异。花费在列表导航数组迭代和元数据查找上的时间花费在反射调用中。
import java.lang.reflect.Field;
import java.util.Random;
public class Reflection {
static final int ITERATIONS = 100;
static final String[] STRINGS = { "asdf", "qwer", "dfgh", "scvb", "ertyerty" };
static final Random random = new Random(System.currentTimeMillis());
static Field fielda;
static Field fieldb;
static Field fieldc;
static Field fieldd;
static Field fielde;
static Field fieldf;
static Field fieldg;
static Field fieldh;
static Field fieldi;
static Field fieldj;
static Field fieldk;
static Field fieldl;
static {
try {
fielda = Blah.class.getField("a");
fieldb = Blah.class.getField("b");
fieldc = Blah.class.getField("c");
fieldd = Blah.class.getField("d");
fielde = Blah.class.getField("e");
fieldf = Blah.class.getField("f");
fieldg = Blah.class.getField("g");
fieldh = Blah.class.getField("h");
fieldi = Blah.class.getField("i");
fieldj = Blah.class.getField("j");
fieldk = Blah.class.getField("k");
fieldl = Blah.class.getField("l");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
for (int i = 0; true; i++) {
System.out.println("i=" + i + ", direct=" + testDirectCallSpeed() + ", reflective=" + testReflectiveCallSpeed());
}
}
static class Blah {
public String a, b, c, d, e, f;
public int g, h, i, j, k, l;
public String toString() {
StringBuilder sb = new StringBuilder(100);
sb.append(super.toString());
sb.append(", a=").append(a);
sb.append(", b=").append(b);
sb.append(", c=").append(c);
sb.append(", d=").append(d);
sb.append(", e=").append(e);
sb.append(", f=").append(f);
sb.append(", g=").append(g);
sb.append(", h=").append(h);
sb.append(", i=").append(i);
sb.append(", j=").append(j);
sb.append(", k=").append(k);
sb.append(", l=").append(l);
return sb.toString();
}
}
public static long testDirectCallSpeed() {
System.gc();
Blah[] blahs = new Blah[ITERATIONS];
long begin = System.currentTimeMillis();
Blah blah;
for (int i = 0; i < ITERATIONS; i++) {
blah = new Blah();
blah.a = getString();
blah.b = getString();
blah.c = getString();
blah.d = getString();
blah.e = getString();
blah.f = getString();
blah.g = getInt();
blah.h = getInt();
blah.i = getInt();
blah.j = getInt();
blah.k = getInt();
blah.l = getInt();
blahs[i] = blah;
}
long exectionTime = System.currentTimeMillis() - begin;
printRandomBlah(blahs);
return exectionTime;
}
public static long testReflectiveCallSpeed() throws Exception {
System.gc();
Blah[] blahs = new Blah[ITERATIONS];
long begin = System.currentTimeMillis();
Blah blah;
for (int i = 0; i < ITERATIONS; i++) {
blah = new Blah();
fielda.set(blah, getString());
fieldb.set(blah, getString());
fieldc.set(blah, getString());
fieldd.set(blah, getString());
fielde.set(blah, getString());
fieldf.set(blah, getString());
fieldg.set(blah, getInt());
fieldh.set(blah, getInt());
fieldi.set(blah, getInt());
fieldj.set(blah, getInt());
fieldk.set(blah, getInt());
fieldl.set(blah, getInt());
blahs[i] = blah;
}
long executionTime = System.currentTimeMillis() - begin;
printRandomBlah(blahs);
return executionTime;
}
public static void printRandomBlah(Blah[] blahs) {
// System.out.println(blahs[random.nextInt(blahs.length)]);
}
public static int getInt() {
return random.nextInt();
}
public static String getString() {
return STRINGS[random.nextInt(STRINGS.length)];
}
}