5

The consensus seems to be that there is a performance benefit to marking member variables as final because they never need reloading from main memory. My question is, do javac or Hotspot automatically do this for me when it's obvious the variable cannot change. eg will javac make 'x' final in this class below...

public class MyClass {
   private String x;

   MyClass(String x) {
      this.x = x;
   }

   public String getX() {
      return x;
   }
}

On a secondary point, has anyone produced empirical evidence that marking members as final makes code run faster? Any benefit is surely negligible in any application making remote calls or database lookups?

Vladimir Ivanov
  • 42,730
  • 18
  • 77
  • 103
barclar
  • 523
  • 4
  • 11
  • 4
    "it's obvious the variable cannot change" - it's not obvious because of Java's reflection capabilities. – hoha Apr 05 '11 at 09:14
  • FYI: Measuring performance gains is difficult: ["Performance Anxiety" by Joshua Bloch](http://parleys.com/#id=2103&st=5) – Adam Paynter Apr 05 '11 at 09:41

4 Answers4

4

Like many performance "enhancements" it is usually a better to ask; What is easier to understand and reason about? e.g. if a field is final I know it won't be changed anywhere. This is often leads to more optimial code, but more importantly it should be more maintainable code. ;)

Certainly, I make any field which can be final as final. Personally I would have preferred that final be the default behaviour and you had to use a keyword like var to make it mutable.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 2
    +1 and yes it would've been nice if `final` was the default, that along with `private` for member variables. – WhiteFang34 Apr 05 '11 at 10:40
  • 1
    That way fields are only mutable and accessible to other classes if you actually intended to do this. – Peter Lawrey Apr 05 '11 at 10:45
  • I agree in principal, that one should write readable and maintainable code, though am not convinced liberal use of `final` increases readability. Also, I see people rewriting code solely to introduce final, say refactoring this `String x; if (coming) { x = "hello"; } else { if (Math.random() > 0.4) { x = "goodbye"; } else { x = "be gone!"; } }` as `final String x = coming ? "hello" : (Math.random() > 0.4 ? "goodbye" : "be gone!");` – barclar Apr 06 '11 at 10:15
  • @user329736, I would probably write the second, even though I only suggest `final` fields should be encouraged/the default behaviour (esp when there are no other code changes required) `final` variables are useful in methods which are large in which case they should be refactored into multiple smaller methods IMHO. – Peter Lawrey Apr 06 '11 at 12:58
  • 1
    @barclar whether you use (nested) `if` statements or a conditional expression (aka ternary operator), has nothing to do with the decision to add `final` to the variable. You can add a `final` modifier to the variable in either case. Regarding the question, there’s no point in the Hotspot optimizer adding a `final` modifier. The only potential benefit from a `final` modifier is to hint that the variable never changes, so when the optimizer detected that the variable never changes, it doesn’t need to add a hint about the thing it already detected. – Holger Jun 01 '23 at 10:57
2

Allowing javac to do this would be a blunder. As there might be code in a different jar which may rely on the code being compiled (modularity), changing code at compile time for optimization sake is not a feasible option.

As for the second argument "never need reloading from the main memory", one needs to remember that most instance variables are cached. final only indicates immutability, it does not guarantee volatility (volatile == always get latest from main memory). Hence the need for locks and volatile keyword in multi-threaded environment.

As for the case with hotspot, I have no clue, and would like to hear more about it. final constants may be in-lined at compile time, thus allowing moderate performance gains. Reference to a question on in-lining in java

Edit:

Note that final indicates immutability needs to be taken with a grain of salt. It does not guarantee that the state cannot change, it only specifies that the object reference can be modified. final indicates immutability for primitive data types
Community
  • 1
  • 1
questzen
  • 3,260
  • 18
  • 21
1

AFAIK, they do not, and thus, you suffer minor penalty. This, however, can be done automatically with IDE tools like Eclipse "Cleanup" feauture.

Alex Abdugafarov
  • 6,112
  • 7
  • 35
  • 59
0

I believe a modern JVM (the Hotspot compiler) does detect that the value doesn't change, so there is no performance benefit in making parameters or variables final yourself. (If this is wrong, please provide a link or test case.) There is one exception: constants (static final).

However, this may be different with final methods and classes. It may improve performance in this case (I'm not completely sure in what cases). By the way, what does improve performance a little bit is making functions static (if possible).

The problem I have with final is that it clutters the code. It would be nice if final would be the default.

Thomas Mueller
  • 48,905
  • 14
  • 116
  • 132