Does use of final keyword in Java improve the performance?

In Java we see lots of places where the final keyword can be used but its use is uncommon.

For example:

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

In the above case, str can be final but this is commonly left off.

When a method is never going to be overridden we can use final keyword. Similarly in case of a class which is not going to be inherited.

Does the use of final keyword in any or all of these cases really improve performance? If so, then how? Please explain. If the proper use of final really matters for performance, what habits should a Java programmer develop to make best use of the keyword?


Usually not. For virtual methods, HotSpot keeps track of whether the method has actually been overridden, and is able to perform optimizations such as inlining on the assumption that a method hasn't been overridden - until it loads a class which overrides the method, at which point it can undo (or partially undo) those optimizations.

(Of course, this is assuming you're using HotSpot - but it's by far the most common JVM, so...)

To my mind you should use final based on clear design and readability rather than for performance reasons. If you want to change anything for performance reasons, you should perform appropriate measurements before bending the clearest code out of shape - that way you can decide whether any extra performance achieved is worth the poorer readability/design. (In my experience it's almost never worth it; YMMV.)

EDIT: As final fields have been mentioned, it's worth bringing up that they are often a good idea anyway, in terms of clear design. They also change the guaranteed behaviour in terms of cross-thread visibility: after a constructor has completed, any final fields are guaranteed to be visible in other threads immediately. This is probably the most common use of final in my experience, although as a supporter of Josh Bloch's "design for inheritance or prohibit it" rule of thumb, I should probably use final more often for classes...


Short answer: don't worry about it!

Long answer:

When talking about final local variables keep in mind that using the keyword final will help the compiler optimize the code statically, which may in the end result in faster code. For example, the final Strings a + b in the example below are concatenated statically (at compile time).

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");

    }

}

The result?

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

Tested on Java Hotspot VM 1.7.0_45-b18.

So how much is the actual performance improvement? I don't dare say. In most cases probably marginal (~270 nanoseconds in this synthetic test because the string concatenation is avoided altogether - a rare case), but in highly optimized utility code it might be a factor. In any case the answer to the original question is yes, it might improve performance, but marginally at best.

Compile-time benefits aside, I could not find any evidence that the use of the keyword final has any measurable effect on performance.

Edit: When decompiling the code using javap -c FinalTest.class the following instructions are obtained:

 public static java.lang.String testFinal();
    Code:
       0: ldc           #16                 // String a
       2: astore_0
       3: ldc           #18                 // String b
       5: astore_1
       6: ldc           #20                 // String ab
       8: areturn

  public static java.lang.String testNonFinal();
    Code:
       0: ldc           #16                 // String a
       2: astore_0
       3: ldc           #18                 // String b
       5: astore_1
       6: new           #24                 // class java/lang/StringBuilder
       9: dup
      10: aload_0
      11: invokestatic  #26                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
      14: invokespecial #32                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
      17: aload_1
      18: invokevirtual #35                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: invokevirtual #39                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      24: areturn

As the testFinal() method has less instructions than testNonFinal() , it will be faster.


YES it can. Here is an instance where final can boost performance:

Conditional compilation is a technique in which lines of code are not compiled into the class file based on a particular condition. This can be used to remove tons of debugging code in a production build.

consider the following:

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (doSomething) {
       // do first part. 
    }

    if (doSomething) {
     // do second part. 
    }

    if (doSomething) {     
      // do third part. 
    }

    if (doSomething) {
    // do finalization part. 
    }
}

By converting the doSomething attribute into a final attribute, you have told the compiler that whenever it sees doSomething, it should replace it with false as per the compile-time substitution rules. The first pass of the compiler changes the code to something like this:

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (false){
       // do first part. 
    }

    if (false){
     // do second part. 
    }

    if (false){
      // do third part. 
    }

    if (false){
    // do finalization part. 

    }
}

Once this is done, the compiler takes another look at it and sees that there are unreachable statements in the code. Since you are working with a top-quality compiler, it doesn't like all those unreachable byte codes. So it removes them, and you end up with this:

public class ConditionalCompile {


  private final static boolean doSomething= false;

  public static void someMethodBetter( ) {

    // do first part. 

    // do second part. 

    // do third part. 

    // do finalization part. 

  }
}

thus reducing any excessive codes, or any unnecessary conditional checking.

Edit: As an example, let's take the following code:

public class Test {
    public static final void main(String[] args) {
        boolean x = false;
        if (x) {
            System.out.println("x");
        }
        final boolean y = false;
        if (y) {
            System.out.println("y");
        }
        if (false) {
            System.out.println("z");
        }
    }
}

When compiling this code with Java 8 and decompiling with javap -c Test.class we get:

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static final void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: ifeq          14
       6: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       9: ldc           #22                 // String x
      11: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      14: iconst_0
      15: istore_2
      16: return
}

We can note that compiled code includes only the non-final variable x . This prooves that final variables have impact on performances, at least for this simple case.

链接地址: http://www.djcxy.com/p/20852.html

上一篇: 在Java中使用final类

下一篇: 在Java中使用final关键字可以提高性能吗?