【发布时间】:2014-10-14 02:30:42
【问题描述】:
我一直试图了解使用new 实例化对象与使用Class.forName("A").newInstance(); 之间的区别。
我为一个简单的类 A 运行了以下代码,它显示使用 Class.forname("A").newInstance() 比仅使用 new A() 慢 70-100 倍。
我很想知道为什么会有这样的时间差异,但无法弄清楚。请有人帮我理解原因。
public class Main4test {
public Main4test() {
}
static int turns = 9999999;
public static void main(String[] args) {
new Main4test().run();
}
public void run() {
System.out.println("method1: " + method1() + "");
System.out.println("method2:" + method2() + "");
}
public long method2() {
long t = System.currentTimeMillis();
for (int i = 0; i < turns; i++) {
try {
A a = (A) Class.forName("A").newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return System.currentTimeMillis() - t;
}
public long method1() {
long t = System.currentTimeMillis();
for (int i = 0; i < turns; i++) {
try {
A a = new A();
} catch (Exception e) {
e.printStackTrace();
}
}
return System.currentTimeMillis() - t;
}
}
public class A {
int a;
public A() {
a=0;
}
}
【问题讨论】:
-
我的猜测是它按名称查找类是一项昂贵的操作。编译器对类一无所知,因此无法进行任何优化。
-
另外,您可能需要对实例进行一些操作,以确保编译器不会对其进行优化。
-
它是反射,它允许按名称创建类的新实例。它也较慢。它加载类并初始化它的静态部分,因此由于副作用,它用于加载驱动程序。
-
通过反射完成任务几乎总是比直接完成要慢。使用
new A(),您有一个构造函数调用。使用Class.forName("A").newInstance(),您有两个方法调用,在构造函数调用之上,这两个方法都可能涉及对二进制文件结构的复杂检查。这只是一种更迂回的方式。 -
在没有 try-catch-block 的情况下,
method1可能会更快,这根本不是必需的。
标签: java reflection