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.ou
You are really asking about two (at least) different cases:
final
for local variablesfinal
for methods/classesJon Skeet has already answered 2). About 1):
I don't think it makes a difference; for local variables, the compiler can deduce whether the variable is final or not (simply by checking whether it is assigned more than once). So if the compiler wanted to optimize variables that are only assigned once, it can do so no matter whether the variable is actually declared final
or not.
final
might make a difference for protected/public class fields; there it's very difficult for the compiler to find out if the field is being set more than once, as it could happen from a different class (which may not even have been loaded). But even then the JVM could use the technique Jon describes (optimize optimistically, revert if a class is loaded which does change the field).
In summary, I don't see any reason why it should help performance. So this kind of micro-optimization is unlikely to help. You could try benchmarking it to make sure, but I doubt it will make a difference.
Edit:
Actually, according to Timo Westkämper's answer, final
can improve performance for class fields in some cases. I stand corrected.
Note: Not a java expert
If I remember my java correctly, there would be very little way to improve performance using the final keyword. I've always known it to exist for "good code" - design and readability.
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.
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...
I'm not an expert but I suppose you should add final
keyword to the class or method if it won't be overwritten and leave variables alone. If there will be any way to optimize such things the compiler will do that for you.
Actually, while testing some OpenGL-related code, I found that using the final modifier on a private field can degrade performance. Here is the start of the class I tested:
public class ShaderInput {
private /* final */ float[] input;
private /* final */ int[] strides;
public ShaderInput()
{
this.input = new float[10];
this.strides = new int[] { 0, 4, 8 };
}
public ShaderInput x(int stride, float val)
{
input[strides[stride] + 0] = val;
return this;
}
// more stuff ...
And this is the method I used to test the performance of various alternatives, amongst which the ShaderInput class:
public static void test4()
{
int arraySize = 10;
float[] fb = new float[arraySize];
for (int i = 0; i < arraySize; i++) {
fb[i] = random.nextFloat();
}
int times = 1000000000;
for (int i = 0; i < 10; ++i) {
floatVectorTest(times, fb);
arrayCopyTest(times, fb);
shaderInputTest(times, fb);
directFloatArrayTest(times, fb);
System.out.println();
System.gc();
}
}
After the 3rd iteration, with the VM warmed up, I consistently got these figures without the final key word:
Simple array copy took : 02.64
System.arrayCopy took : 03.20
ShaderInput took : 00.77
Unsafe float array took : 05.47
With the final keyword:
Simple array copy took : 02.66
System.arrayCopy took : 03.20
ShaderInput took : 02.59
Unsafe float array took : 06.24
Note the figures for the ShaderInput test.
It didn't matter whether I made the fields public or private.
Incidentally, there are a few more baffling things. The ShaderInput class outperforms all other variants, even with the final keyword. This is remarkable b/c it basically is a class wrapping a float array, while the other tests directly manipulate the array. Have to figure this one out. May have something to do with ShaderInput's fluent interface.
Also System.arrayCopy actually apparently is somewhat slower for small arrays than simply copying elements from one array to the other in a for loop. And using sun.misc.Unsafe (as well as direct java.nio.FloatBuffer, not shown here) performs abysmally.