在 Java 中使用 final 关键字是否会提高性能?

2022-08-31 04:41:16

在Java中,我们看到很多地方可以使用关键字,但它的使用并不常见。final

例如:

String str = "abc";
System.out.println(str);

在上述情况下,可以,但这通常被忽略。strfinal

当一个方法永远不会被覆盖时,我们可以使用最终关键字。同样,对于不会被继承的类。

在任何或所有这些情况下使用 final 关键字是否真的能提高效果?如果是这样,那么如何?请解释。如果正确使用对性能真的很重要,那么Java程序员应该养成什么习惯才能充分利用关键字?final


答案 1

通常不会。对于虚拟方法,HotSpot 会跟踪该方法是否实际上已被覆盖,并且能够执行优化,例如在假设方法未被覆盖的情况下进行内联 - 直到它加载一个重写该方法的类,此时它可以撤消(或部分撤消)这些优化。

(当然,这是假设你正在使用HotSpot - 但它是迄今为止最常见的JVM,所以...)

在我看来,您应该基于清晰的设计和可读性而不是出于性能原因而使用。如果出于性能原因想要更改任何内容,则应在将最清晰的代码弯曲变形之前执行适当的测量 - 这样您就可以决定实现的任何额外性能是否值得较差的可读性/设计。(根据我的经验,这几乎不值得;YMMV.)final

编辑:正如最后提到的字段一样,值得一提的是,就清晰的设计而言,它们通常是一个好主意。它们还改变了跨线程可见性方面的保证行为:构造函数完成后,任何最终字段都保证立即在其他线程中可见。根据我的经验,这可能是最常见的用法,尽管作为Josh Bloch的“设计继承或禁止继承”经验法则的支持者,我应该更频繁地用于课程......finalfinal


答案 2

简短的回答:别担心!

长答案:

在谈论最终的局部变量时,请记住,使用关键字将有助于编译器静态优化代码,这最终可能会导致更快的代码。例如,以下示例中的最后一个字符串是静态串联的(在编译时)。finala + b

public class FinalTest {

    public static final int N_ITERATIONS = 1000000;

    public static String testFinal() {
        final String a = "a";
        final String b = "b";
        return a + b;
    }

    public static String testNonFinal() {
        String a = "a";
        String b = "b";
        return a + b;
    }

    public static void main(String[] args) {
        long tStart, tElapsed;

        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method with finals took " + tElapsed + " ms");

        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testNonFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method without finals took " + tElapsed + " ms");

    }

}

结果呢?

Method with finals took 5 ms
Method without finals took 273 ms

已在 Java Hotspot VM 1.7.0_45-b18 上测试。

那么实际性能改进了多少呢?我不敢说。在大多数情况下,可能是微不足道的(在这个综合测试中约为270纳秒,因为完全避免了字符串串联 - 这种情况很少见),但在高度优化的实用程序代码中,这可能是一个因素。无论如何,原始问题的答案是肯定的,它可能会提高性能,但充其量只是微不足道的

撇开编译时的好处不谈,我找不到任何证据表明关键字的使用对性能有任何可衡量的影响。final


推荐