Reputation: 6366
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?
Upvotes: 417
Views: 123837
Reputation: 414
In Java we make things immutable with the final
keyword and there are at least 3 ways in which immutability can make some real difference in code performance. Those 3 points have their common origin in making the compiler or the developer doing better assumptions:
As stated by many of the other replies and comments, making classes immutable leads to cleaner and more maintainable code, and making objects immutable makes them easier to handle, because they can be in exactly one state, so this translates to easier concurrency and an optimization of the time needed to accomplish tasks.
Furthermore the compiler warns you about the usage of an uninitialized variable and won't let you reassign it with a new value.
If we talk about method parameters, declaring them final
would make the compiler complaint if you accidentally use the same name for a variable, or reassign it's value (making the parameter no more accessible).
A simple analysis of the generated bytecode should put the last world to the performance question: using a minimally modified version of the code posted by @rustyx in his reply, you can see that the generated bytecode is different when the compiler knows that objects won't mutate their value.
That's the code:
public class FinalTest {
private static final int N_ITERATIONS = 1000000;
private static String testFinal() {
final String a = "a";
final String b = "b";
return a + b;
}
private static String testNonFinal() {
String a = "a";
String b = "b";
return a + b;
}
private static String testSomeFinal() {
final String a = "a";
String b = "b";
return a + b;
}
public static void main(String[] args) {
measure("testFinal", FinalTest::testFinal);
measure("testSomeFinal", FinalTest::testSomeFinal);
measure("testNonFinal", FinalTest::testNonFinal);
}
private static void measure(String testName, Runnable singleTest){
final long tStart = System.currentTimeMillis();
for (int i = 0; i < N_ITERATIONS; i++)
singleTest.run();
final long tElapsed = System.currentTimeMillis() - tStart;
System.out.printf("Method %s took %d ms%n", testName, tElapsed);
}
}
compiling it with openjdk17: javac FinalTest.java
then decompiling: javap -c -p FinalTest.class
lead to this bytecode:
private static java.lang.String testFinal();
Code:
0: ldc #7 // String ab
2: areturn
private static java.lang.String testNonFinal();
Code:
0: ldc #9 // String a
2: astore_0
3: ldc #11 // String b
5: astore_1
6: aload_0
7: aload_1
8: invokedynamic #13, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
13: areturn
private static java.lang.String testSomeFinal();
Code:
0: ldc #11 // String b
2: astore_0
3: aload_0
4: invokedynamic #17, 0 // InvokeDynamic #1:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
9: areturn
// omitted bytecode for the measure() method, which is not interesting
As you can see, there are cases where the final
keyword makes a difference.
For the sake of completeness those are the measured times:
Method testFinal took 5 ms
Method testSomeFinal took 13 ms
Method testNonFinal took 20 ms
Those times seems to be irrelevant (given that we accomplished 1 million tasks), but I think that, after some while, JIT optimization is doing it's magic and smooths out the differences, but even with that said, 4x is not that negligible, considering that, when it comes to testNonFinal
turn, the JVM is warmed up by the previous tests, and the common code should yet be optimized.
Less bytecode translates also to easier and shorter inlining, and so better usage of the resources and better performance.
Java developers can potentially write code that runs on servers, desktops and small or embedded devices, so making code more efficient at compile time (and not completely relying on the JVM optimizations) can save memory, time and energy on all the runtimes and lead to less concurrency problems and errors.
If objects have final or immutable fields, their state can't change and the memory they need is more easily estimated when they are created (so this lead to fewer relocations) and need less defensive copies: in a getter I can directly share an immutable object, without creating a defensive copy.
Finally there's another point about future possibilities: when project Valhalla will see the sunlight and "value classes" will be available, having applied immutability to objects' fields will be a significant simpification for those who want to use them, and take advantage of numerous JIT-compiler optimizations that could came out.
If variables, objects' properties and methods' parameters had been immutable by default in Java (like in Rust), the developers would have been forced to write cleaner and better performing code, and explicitly declaring mutable
all the objects which can mutate their value would have made developers more conscious about possible errors.
I don't know if for final class
es would be the same, because mutable class
does not sound that meaningful to me
Upvotes: 7
Reputation: 150
I cannot say it is uncommon because as far as I know it is the only way of declaring a constant in java. As a javascript developer, I know how important the keyword constant is. If you are working in production level, and you have values that can never be changed even accidentally by other coders, values such as SSN number or even names. Then you have to use the final keyword to declare variables. Sometimes it can be very troublesome if certain classes can be inherited. Because if many people are working in a team someone can inherit a class, extend it and even make changes to the variables and methods of the parent class. This can be stopped with the keyword final because even static variables can be changed unless the final keyword is used. As far as your question is concerned I do not think the final keyword can affect the performance of the code, but it can definitely prevent human errors by making sure that other team members do not accidentally modify anything that needs to remain constant.
Upvotes: 0
Reputation: 9405
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.
Upvotes: 89
Reputation: 120848
I am amazed that no one has actually posted some real code that is de-compiled to prove that there is at least some minor difference.
For the reference this has been tested against javac
version 8
, 9
and 10
.
Suppose this method:
public static int test() {
/* final */ Object left = new Object();
Object right = new Object();
return left.hashCode() + right.hashCode();
}
Compiling this code as it is, produces the exact same byte code as when final
would have been present (final Object left = new Object();
).
But this one:
public static int test() {
/* final */ int left = 11;
int right = 12;
return left + right;
}
Produces:
0: bipush 11
2: istore_0
3: bipush 12
5: istore_1
6: iload_0
7: iload_1
8: iadd
9: ireturn
Leaving final
to be present produces:
0: bipush 12
2: istore_1
3: bipush 11
5: iload_1
6: iadd
7: ireturn
The code is pretty much self-explanatory, in case there is a compile time constant, it will be loaded directly onto the operand stack (it will not be stored into local variables array like the previous example does via bipush 12; istore_0; iload_0
) - which sort of makes sense since no one can change it.
On the other hand why in the second case the compiler does not produce istore_0 ... iload_0
is beyond me, it's not like that slot 0
is used in any way (it could shrink the variables array this way, but may be Im missing some internals details, can't tell for sure)
I was surprised to see such an optimization, considering how little ones javac
does. As to should we always use final
? I'm not even going to write a JMH
test (which I wanted to initially), I am sure that the diff is in the order of ns
(if possible to be captured at all). The only place this could be a problem, is when a method could not be inlined because of it's size (and declaring final
would shrink that size by a few bytes).
There are two more final
s that need to be addressed. First is when a method is final
(from a JIT
perspective), such a method is monomorphic - and these are the most beloved ones by the JVM
.
Then there are final
instance variables (that must be set in every constructor); these are important as they will guarantee a correctly published reference, as touched a bit here and also specified exactly by the JLS
.
That being said : there is one more thing that is invisible to every single answer here: garbage collection
. It is going to take a lot of time to explain, but when you read a variable, a GC
has a so-called barrier
for that read. Every aload
and getField
is "protected" via such a barrier, a lot more details here. In theory, final
fields do not need such a "protection" (they can skip the barrier entirely). So if a GC does that - final
will improve performance.
Upvotes: 27
Reputation: 56
As mentioned elsewhere, 'final' for a local variable, and to a slightly lesser extent a member variable, is more a matter of style.
'final' is a statement that you intend the variable to not change (i.e., the variable won't vary!). The compiler can then help you out by complaining if you violate your own constraint.
I share the sentiment that Java would have been a better language if identifiers (I'm sorry, I just cannot call a non-varying thing a 'variable') were final by default, and required you to explicitly say that they were variables. But having said that, I don't generally use 'final' on local variables that are initialized and never assigned; it just seems too noisy.
(I do use final on member variables)
Upvotes: 3
Reputation: 62769
Final (At least for member variables and parameters) is more for humans then it is for the machine.
It's good practice to make variables final wherever possible. I wish Java had made "variables" final by default and had a "Mutable" keyword to allow changes. Immutable classes lead to much better threaded code, and just glancing at a class with "final" in front of each member will quickly show it to be immutable.
Another case--I've been converting a lot of code to use @NonNull/@Nullable annotations (You can say a method parameter must not be null then the IDE can warn you every place you pass a variable that isn't tagged @NonNull--the whole thing spreads to a ridiculous degree). It's much easier to prove a member variable or parameter can't be null when it's tagged final since you know it's not being re-assigned anywhere else.
My suggestion is to get in the habit of applying final for members and parameters by default, It's just a few characters but will nudge you towards improving your coding style if nothing else.
Final for methods or classes is another concept since it disallows a very valid form of reuse and doesn't really tell the reader much. The best use is probably the way they made String and the other intrinsic types final so you could rely on consistent behavior everywhere--That prevented a lot of bugs (although there are times I would have LOVED to extend string.... oh the possibilities)
Upvotes: 2
Reputation: 85341
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.
Upvotes: 114
Reputation: 239
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.
Upvotes: 2
Reputation: 19
final
keyword can be used in five ways in Java.
A class is final: a class is final means we cannot be extended or inheritance means inheritance is not possible.
Similarly - A object is final: some time we does not modified the internal state of object so in such case we can specify the object is final object.object final means not variable also final.
Once reference variable is made final, it cannot be reassigned to other object. But can change the contents of the object as long as its fields are not final
Upvotes: -4
Reputation: 1500504
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...
Upvotes: 328
Reputation: 44376
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.
Upvotes: 1
Reputation: 83609
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.
Upvotes: 13
Reputation: 3017
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.
Upvotes: 6
Reputation: 5735
According to IBM - it doesnt for classes or methods.
http://www.ibm.com/developerworks/java/library/j-jtp04223.html
Upvotes: 38