Java反射性能

问题

使用反射创建对象而不是调用类构造函数会导致任何显着的性能差异吗?


#1 热门回答(146 赞)

**是的 - 绝对。**通过反射来升级课程的幅度更大。

QuotingJava's documentation on reflection

由于反射涉及动态解析的类型,因此无法执行某些Java虚拟机优化。因此,反射操作的性能低于非反射操作,并且应避免在性能敏感应用程序中频繁调用的代码段中。

这是一个简单的测试,我在机器上运行5分钟,运行Sun JRE 6u10:

public class Main {

    public static void main(String[] args) throws Exception
    {
        doRegular();
        doReflection();
    }

    public static void doRegular() throws Exception
    {
        long start = System.currentTimeMillis();
        for (int i=0; i<1000000; i++)
        {
            A a = new A();
            a.doSomeThing();
        }
        System.out.println(System.currentTimeMillis() - start);
    }

    public static void doReflection() throws Exception
    {
        long start = System.currentTimeMillis();
        for (int i=0; i<1000000; i++)
        {
            A a = (A) Class.forName("misc.A").newInstance();
            a.doSomeThing();
        }
        System.out.println(System.currentTimeMillis() - start);
    }
}

有了这些结果:

35 // no reflection
465 // using reflection

请记住,查找和实例化是一起完成的,在某些情况下,查找可以重构,但这只是一个基本的例子。

即使你只是实例化,你仍然会受到性能影响:

30 // no reflection
47 // reflection using one lookup, only instantiating

再次,YMMV。


#2 热门回答(77 赞)

是的,它慢了。

但请记住该死的#1规则 - PREMATURE OPTIMIZATION是所有邪恶的根源

(好吧,DRY可能与#1并列)

我发誓,如果有人在工作时向我求助并告诉我这一点,我会对他们未来几个月的代码非常警惕。

在你确定需要它之前,你必须永远不会优化,直到那时,只需编写好的,可读的代码。

哦,我也不是说写愚蠢的代码。只是考虑一下你可以做到的最干净的方式 - 没有复制和粘贴等等(仍然要警惕内部循环和使用最符合你需要的集合 - 忽略这些不是"未经优化的"编程,这是"糟糕"的编程)

当我听到这样的问题时,它吓坏了我,但后来我忘了每个人都必须在他们真正得到它之前先学习所有的规则。你花了一个月的时间调试了一些"优化"的东西后你会得到它。

编辑:

这个帖子发生了一件有趣的事情。检查#1答案,这是编译器在优化方面有多强大的一个例子。测试完全无效,因为可以完全排除非反射实例化。

课?在编写一个干净,整齐编码的解决方案并证明它太慢之前,不要进行优化。


#3 热门回答(33 赞)

你可能会发现J a正在优化A a = new A()。如果将对象放入数组中,它们的表现就不那么好了。 ;)以下打印...

new A(), 141 ns
A.class.newInstance(), 266 ns
new A(), 103 ns
A.class.newInstance(), 261 ns

public class Run {
    private static final int RUNS = 3000000;

    public static class A {
    }

    public static void main(String[] args) throws Exception {
        doRegular();
        doReflection();
        doRegular();
        doReflection();
    }

    public static void doRegular() throws Exception {
        A[] as = new A[RUNS];
        long start = System.nanoTime();
        for (int i = 0; i < RUNS; i++) {
            as[i] = new A();
        }
        System.out.printf("new A(), %,d ns%n", (System.nanoTime() - start)/RUNS);
    }

    public static void doReflection() throws Exception {
        A[] as = new A[RUNS];
        long start = System.nanoTime();
        for (int i = 0; i < RUNS; i++) {
            as[i] = A.class.newInstance();
        }
        System.out.printf("A.class.newInstance(), %,d ns%n", (System.nanoTime() - start)/RUNS);
    }
}

这表明我的机器差异大约为150 ns。