15

I know how the compiler interprets the final keyword in Java, but how should us programmers interpret its meaning? Should it be:

1) This variable cannot be changed (used by inner class for example)

or

2) I'm not planning to change this variable (might have some optimisation benefits for member variables).

I'm asking because I've worked on code where everything is declared final by default (option 2 above) which, in my opinion, devalues the keyword and hides the values that really can't change! Is there still performance benefits in declaring variables final?

StuPointerException
  • 7,117
  • 5
  • 29
  • 54

9 Answers9

17

Everything being final by default is a good thing. The more you can model your code on immutability, the easier it tends to be to reason about.

Using final is hardly ever about performance in my opinion. It's about making assertions about the rest of the code (nothing changes this variable) which can help a reader to understand the code, and can be checked by the compiler.

EDIT: The above is my view for fields. For local variables (including parameters) I personally only use final when the variable will be used in an anonymous inner class. This is different from fields because:

  • It's easy to see the whole context of the method - and if it's not, that's a problem in itself.
  • As it doesn't represent the state of an object (or class) the benefits of immutability don't really apply.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I accept this for member variables, what about local variables and parameters? Surely there is little benefit in marking them as final unless they really need to be? – StuPointerException Aug 01 '13 at 12:25
  • The only gripe I have with `final` is that I need to write it at all. For example, it emaciates method signatures so I don't use it there. Instead I have a compiler warning of a changing parameter. – Marko Topolnik Aug 01 '13 at 12:41
  • 1
    @StuPointerException: For local variables and parameters I personally agree - I only use it for variables which need to be used in inner classes. Will edit to indicate this. – Jon Skeet Aug 01 '13 at 12:44
  • 1
    @MarkoTopolnik Sure, Java should have had the opposite: a keyword like 'var' or 'mutable'. – Christophe Roussy Aug 01 '13 at 12:45
  • But let me ask you this, Jon: would you complain and be generally frustrated if the default for a variable/parameter was `final`? – Marko Topolnik Aug 01 '13 at 12:53
  • @MarkoTopolnik: Nope, I think that would be good (and ditto in C#) with a modifier to say that you want it to vary. Unless it's declared as an iteration variable in a `for` loop, probably! It's just that the benefit isn't worth the cruft of adding `final` everywhere IMO. – Jon Skeet Aug 01 '13 at 12:54
  • Even `for`s would be nicer if the semantics were such that there was a new binding for the `final` var in each iteration, and within the iteration block itself it couldn't mutate. – Marko Topolnik Aug 01 '13 at 12:59
  • @MarkoTopolnik: Usually, yes - with very occasional differences. – Jon Skeet Aug 01 '13 at 13:03
  • Definitely there would have to be a way to do it the old-fashioned way, but I'd expect an extra modifier for that case. – Marko Topolnik Aug 01 '13 at 13:05
  • 1
    I think the verbosity of "`final`" has discouraged its use. In Scala for example, `final` variables are *much* more common because it's simply a matter of writing `val` instead of `var`. I was recently thinking that it would be cool to have a new assignment operator for `final` variables, e.g. `:=` (and the `final` keyword could then be omitted of course). – arshajii Aug 01 '13 at 13:33
  • @arshajii: Yup, that sounds correct to me. I believe the C# team were considering introducing `val` too, but felt that its closeness to `var` was unfortunately. – Jon Skeet Aug 01 '13 at 13:35
6

The final keyword should be abandoned, it should be standard in all applicable cases, and the finality should only be revokable with a keyword like

this_variable_will_change_unexpectedly_behind_your_back

This keyword should not get autocompleted by any IDE, and it shoud not be possible to insert it with Ctrl-V.

Ingo
  • 36,037
  • 5
  • 53
  • 100
4

I wrote a post about this a while ago.

Final helps reading code:

  • without the use of final everything may be mutable (potential mess)
  • it forces setting a variable before it can be used (useful in constructors)

By using final you tell the compiler something about your code and it helps you in return.

Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85
1

The 2nd option is a safeguard. It stops you from accidentally changing or reassigning. As such it's useful to provide and you can remove when you decide you want that variable to change.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
1

I can't add much to what Jon has already said, but just for completeness, JLS 17.5.3 says final fields also may lead to optimizations;

If a final field is initialized to a compile-time constant expression (§15.28) in the field declaration, changes to the final field may not be observed, since uses of that final field are replaced at compile time with the value of the constant expression.

Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
0

I don't understand why you think there's lack of value.

When I see all final variables, it implies that the class is immutable. That's a good thing, because immutable classes are inherently thread safe.

duffymo
  • 305,152
  • 44
  • 369
  • 561
0

final variables are a good thing generally speaking. Note that it only means that the variable can't be reassigned, but the object it points to can change if it is mutable.

Performance wise, final allows more aggressive compiler optimisations:

the specification allows aggressive optimization of final fields. Within a thread, it is permissible to reorder reads of a final field with those modifications of a final field that do not take place in the constructor.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
0

Declaring every variable as final is not devaluing final keyword. It helps developers in debugging the application to rule out possibility of modification of variables, especially during multi threaded environment of application.

With java 8 release, we have one more concept called "effectively final variable"

local variables referenced from a lambda expression must be final or effectively final

A variable is considered effective final if it is not modified after initialization in the local block. This means you can now use the local variable without final keyword inside an anonymous class or lambda expression, provided they must be effectively final.

If you don't want to declare effective final as final variable, this new feature helps you if you are using lambda expressions/anonymous classes. You can avoid declaration of final keyword for effective final variables. Have a look at this article

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
-1

Its true that final variable is used so that no one can change the value, it works as constant in java.

Let me give example

I have created one package which can be used by some other person as well, now there are some configurations variable that are need to set in order to run it properly. lets say its login package. So there can be few encryption options like

encryption_method = HASH_ENCRYPTION

OR

encryption_method = SYMMETRIC_ENCRYPTION

instead of passing integer 1, 2, 3 we can define final variable which helps developer in more readable form and ofcource i don't want user to change it so I keep it final, else internal logic may break

Achal Saraiya
  • 410
  • 5
  • 15