412

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?

Naman
  • 27,789
  • 26
  • 218
  • 353
Abhishek Jain
  • 6,296
  • 7
  • 26
  • 34
  • I don't think so pal, method dispatching(call site caching and ...) is an issue in dynamic languages not in static type languages – Jahan Zinedine Nov 25 '10 at 17:11
  • If I run my PMD tool (plugin to eclipse) used for reviewing purpose, it suggest to make changes for variable in case as shown above. But I did not understand its concept. Really the performance hits so much?? – Abhishek Jain Nov 25 '10 at 17:17
  • 5
    I thought this was a typical exam question. I remember that final *does* have influence on performance, IIRC final classes can be optimized by the JRE in some way because they cannot be subclassed. – Kawu Nov 25 '10 at 19:57
  • I actually had this tested. On all JVMs I tested the use of final on local variables *did* improve performance (slightly, but nevertheless can be a factor in utility methods). The source code is in my answer below. – rustyx Jan 31 '14 at 16:52
  • When doing performance checks, it's best to use a tool like Caliper for microbenchmarks. – Archimedes Trajano Aug 29 '15 at 06:51
  • The only case where performance gains of using final are significant enough to bother about is: you have some really small method like 'long xor(long v1, long v2) {return v1^v2;};' which on other hand takes significant portion of cpu time. By marking v1 and v2 as final you avoid unnecessary copying of these variables (which, obviously, takes more time than operation itself) – Ivan Zaitsau Nov 20 '16 at 22:00
  • And even in the case written above HotSpot usually makes such methods "inline" – Ivan Zaitsau Nov 20 '16 at 22:10
  • 3
    "premature optimization is the root of all evil". Just let the compiler do its work. Write readable and good commented code. That's always the best choice! – kaiser Dec 12 '17 at 23:17

14 Answers14

325

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...

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I like your answer but I would like to know more in details about it. – Abhishek Jain Nov 25 '10 at 17:14
  • 1
    @Abhishek: About what in particular? The most important point is the last one - that you almost certainly shouldn't be worrying about this. – Jon Skeet Nov 25 '10 at 17:23
  • As I have written above in one comment, PMD tool suggest me that particular kind of change but I did not understand the context of the above changes. Yes I am agree with you even I did not find any difference. There are lots of articles related to performance suggest this change. So I would like to know what difference JVM actually make with final keyword and else ...if possible. +1 for your answer. – Abhishek Jain Nov 25 '10 at 17:31
  • 14
    @Abishek: `final` is generally recommended because it makes code easier to understand, and helps find bugs (because it makes the programmers intention explicit). PMD probably recommends to use `final` because of these style issues, not for performance reasons. – sleske Nov 25 '10 at 17:36
  • 3
    @Abhishek: A lot of it is likely to be JVM-specific, and may rely on very subtle aspects of context. For example, I believe the HotSpot *server* JVM will still allow inlining of virtual methods when overridden in one class, with a quick type check where appropriate. But the details are hard to pin down and may well change between released. – Jon Skeet Nov 25 '10 at 17:37
  • I was told that adding the final modifier to a variable is a hint to the JIT that the variable could be stored in a CPU register for faster access. – Javamann Jul 29 '15 at 15:47
  • 13
    Here I would quote Effective Java, 2nd Edition, Item 15, Minimize mutability : `Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure.`. Furthermore `An immutable object can be in exactly one state, the state in which it was created.` vs `Mutable objects, on the other hand, can have arbitrarily complex state spaces.`. From my personal experience, using the keyword `final` should highlight the intent of the developer to lean toward immutability, not to "optimize" code. I encourage you to read this chapter, fascinating ! – Louis F. Feb 17 '16 at 21:59
  • 1
    @JonSkeet this is yet again (you probably dont even keep track of this, which is good) one of those questions where the answer would be "don't bother with these details, do a clear design, etc", unless you *are* all about *these* details... https://stackoverflow.com/a/49417253/1059372 – Eugene Mar 21 '18 at 22:04
  • 2
    Other answers shows that using the `final` keyword on variables could reduce the amount of bytecode, which may produce an effect on performance. – Julien Kronegg May 06 '18 at 21:44
  • Wonderful point in mentioning cross-thread visibility as an added bonus to using final. – blau Apr 01 '22 at 20:27
  • Sorry for the downvote, here's why. I think that the answer is not completely justified by facts: 1. the compiler behaves differently when knows that values are immutable. As an example concatenating final strings results in no operation when they are `final` (the compiler calculate the concatenated string), and the same can be said about other primitive types, on which mathematical operations, bitwise ops and many other can be performed at compile time. 2. Using `final` objects not only make code cleaner, but also ease their garbage collection, but I have too few chars to justify that here – Marco Carlo Moriggi Aug 11 '22 at 13:40
114

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.

rustyx
  • 80,671
  • 25
  • 200
  • 267
  • 5
    I rewrote your code a little to test both cases 100 times. Eventually the average time of the final was 0 ms and 9 ms for the non final. Increasing the iteration count to 10M set the average to 0 ms and 75 ms. The best run for the non final was 0 ms however. Maybe it's the VM detecting results are just being thrown away or something? I don't know, but regardless, the use of final does make a significant difference. – Casper Færgemand Apr 03 '14 at 13:05
  • 8
    Flawed test. Earlier tests will warmup the JVM and benefit the later test invocations. Reorder your tests and see what happens. You need to run each test in its own JVM instance. – Steve Kuo Jun 05 '14 at 21:56
  • 23
    No the test is not flawed, the warmup was taken into account. The second test is SLOWER, not faster. Without warmup the second test would be EVEN SLOWER. – rustyx Jun 06 '14 at 15:26
  • 7
    In testFinal() all time returned the same object, from strings pool, because resust of final strings and strings literals concatenation are evaluated at compile time. testNonFinal() every time return new object, thats explain difference in speed. – anber Jun 18 '14 at 12:56
  • Changing `String a` and `b` to `Integer`s results in no performance difference. @anber is right this benchmark is flawed. It is not related to any realistic scenario. – Kai Dec 08 '14 at 08:26
  • 4
    What makes you think the scenario is unrealistic? `String` concatenation is a much more costly operation than adding `Integers`. Doing it statically (if possible) is more efficient, that's what the test shows. – rustyx Dec 09 '14 at 09:17
  • @RustyX but that's because of the Stringpool? So with any other type of object, it would not work? – El Mac Apr 22 '17 at 06:47
  • 1
    If you pass in the loop variable `i` to the methods `testFinal` and `testNonFinal` and in these methods instead of returning `a + b` you return `a + i + b` then the execution times are identical, as in fact the generated bytecodes are identical – Gergely Toth Jun 23 '17 at 05:04
  • There's NOTHING preventing the JIT to throw away both test methods as the results doesn't get used. The JIT doesn't bother or maybe it's just kind enough to provide you some figures, but the timing could be all zero. See JMH blackhole for how to do it right. – maaartinus Jun 15 '20 at 20:18
  • "~270 nanoseconds in this synthetic test" ... but isn't it *micro*seconds? – Philzen Mar 04 '22 at 21:16
  • 20x seems not to be that little... Consider that Java developers can potentially develop code for any device, so optimizing at compile time should lead to better performance in general, less runtime errors and less energy comsumption on every device / architecture (which is not that irrelevant) – Marco Carlo Moriggi Aug 11 '22 at 14:24
88

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.

mel3kings
  • 8,857
  • 3
  • 60
  • 68
  • 2
    @ŁukaszLech I learned this from an Oreilly book: Hardcore Java, on their chapter regarding the final keyword. – mel3kings Oct 01 '13 at 01:29
  • 23
    This talks about optimization at the compile time, means developer knows the VALUE of the final boolean variable at compile time, what is the whole point of writing if blocks in first place then for this scenario where the IF-CONDITIONS are not necessary and not making any sense? In my opinion, even if this boosts performance, this is wrong code in first place and can be optimized by developer himself rather than passing the responsibility to compiler and the question mainly intends to ask about the performance improvements in usual codes where final is used which makes programmatic sense. – Bhavesh Agarwal Nov 22 '13 at 11:43
  • 11
    The point of this would be to add debugging statements as mel3kings stated. You could flip the variable before a production build (or configure it in your build scripts) and automatically remove all of that code when the distribution is created. – Adam Mar 10 '16 at 13:36
38

According to IBM - it doesnt for classes or methods.

http://www.ibm.com/developerworks/java/library/j-jtp04223.html

wmitchell
  • 5,665
  • 10
  • 37
  • 62
  • 3
    ...and according to IBM, **it does for fields**: https://www.ibm.com/developerworks/java/library/j-jtp1029/index.html#heading6 - and also is promoted as a best practice. – Philzen Oct 31 '19 at 22:14
  • 7
    The article "04223" is from year 2003. Nearly seventeen years old now. That was ... Java 1.4? – dmatej Dec 14 '19 at 19:19
27

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 finals 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.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • I compiled the code using Java 8 (JDK 1.8.0_162) with the debug options (`javac -g FinalTest.java`), decompiled the code using `javap -c FinalTest.class` and did not obtain the same results (with `final int left=12`, I got `bipush 11; istore_0; bipush 12; istore_1; bipush 11; iload_1; iadd; ireturn`). So yes, the generated bytecode dependents on lot of factors and it is difficult to say whether having a `final` or not produce an effect on performance. But as the bytecode is different, some performance difference may exist. – Julien Kronegg May 06 '18 at 22:13
  • 2
    [Isn't this decompiled real code...](https://stackoverflow.com/a/17335215/5267751) – user202729 Jul 14 '18 at 11:34
  • 1
    It's not terribly interesting though what the byte code looks like. Actual assembly code is all that matters. I well suspect that in this case the assembly will ultimately look the same. – Stefan Reich Jan 04 '21 at 17:26
13

You are really asking about two (at least) different cases:

  1. final for local variables
  2. final for methods/classes

Jon 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.

sleske
  • 81,358
  • 34
  • 189
  • 227
  • I don't think the compiler can correctly check the number of times a local variable is assigned: what about if-then-else structs with numerous assignments? – gyorgyabraham Nov 20 '13 at 13:42
  • 1
    @gyabraham: The compiler already checks theses cases if you declare a local variable as `final`, to make sure you do not assign it twice. As far as I can see, the same checking logic can be (and probably is) used for checking whether a variable could be `final`. – sleske Nov 20 '13 at 13:52
  • The final-ness of a local variable is not expressed in the bytecode, thus the JVM doesn't even know that it was final – Steve Kuo Jun 05 '14 at 21:58
  • 1
    @SteveKuo: Even if it is not expressed in the bytecode, it may help `javac` to optimize better. But this is just speculation. – sleske Jun 05 '14 at 22:32
  • 1
    The compiler could find out whether a local variable has been assigned exactly once, but in practice, it doesn’t (beyond error checking). On the other hand, if a `final` variable is of a primitive type or type `String` and is immediately assigned with a compile-time constant like in the question’s example, the compiler *must* inline it, as the variable is a compile-time constant per specification. But for most use cases, the code might look different, but it still makes no difference whether the constant is inlined or read from a local variable performance-wise. – Holger Sep 16 '16 at 17:10
6

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.

Neowizard
  • 2,981
  • 1
  • 21
  • 39
6

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:

  1. More reliable code
  2. More performant code
  3. More efficient memory allocation and garbage collection

More reliable code

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).

More performant code

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.

Easier inlining

Less bytecode translates also to easier and shorter inlining, and so better usage of the resources and better performance.

Embedded devices

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.

More efficient memory allocation and garbage collection

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.

A personal note about immutability

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 classes would be the same, because mutable class does not sound that meaningful to me

2

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)

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • Adding extra annotations and `final`s to code makes it bigger... but does it really make it better? – Ashley Frieze Feb 13 '21 at 09:36
  • Absolutely, and much better. Coding is not typing stuff to make something work, that's basically scriptwriting (which is a totally valid practice, but I wouldn't recommend java for it). Final saves so may problems (and doesn't really make your program bigger--unless for some horrific reason you mean to minimize source code size which is a terrifying concept--why not just code in APL or one of the code-golf languages if that is your goal? Using your code to prevent issues before you encounter them is amazingly useful. – Bill K Mar 24 '21 at 00:38
  • Sure... but... I've seen code with deep rooted issues with final all over the place, and I've seen beautifully easy code without it. How does final specifically help in a way that other practices don't? For example, if you only write very very short functions, and rarely use temp variables, `final` doesn't add so much as look like SHOUTING! ;) – Ashley Frieze Mar 24 '21 at 15:53
2

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)

1

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.

user3663845
  • 209
  • 1
  • 2
  • 8
  • 1
    You forgot to make the parameters final.
    
    public ShaderInput x(final int stride, final float val)
        {
            input[strides[stride] + 0] = val;
            return this;
        }
    
    In my experiences, doing any variable or field final may indeed boost performance.
    – Anticro Nov 28 '16 at 11:36
  • 1
    Oh, and also make the others final too:
    
    final int arraySize = 10;
       final float[] fb = new float[arraySize];
        for (int i = 0; i < arraySize; i++) {
            fb[i] = random.nextFloat();
        }
        final 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();
        }
    
    – Anticro Nov 28 '16 at 11:45
1

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.

Crozin
  • 43,890
  • 13
  • 88
  • 135
0

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.

-4

final keyword can be used in five ways in Java.

  1. A class is final
  2. A reference variable is final
  3. A local variable is final
  4. A method is final

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

adityaraj
  • 19
  • 1