209

In Java, there is a practice of declaring every variable (local or class), parameter final if they really are.

Though this makes the code a lot more verbose, this helps in easy reading/grasping of the code and also prevents mistakes as the intention is clearly marked.

What are your thoughts on this and what do you follow?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
surajs
  • 2,342
  • 2
  • 14
  • 7
  • 15
    This can lead to a religious argument. Some people like it, some people hate it. I like final fields but not final local variables unless they need to be, not sure its entirely rational. Not sure any down-vote would be either. I agree with Alex Miller. ;) – Peter Lawrey Jun 11 '09 at 20:25
  • I can understand if people don't like to have their code cluttered with finals. But this is a problem a good editor could solve: https://bugs.eclipse.org/bugs/show_bug.cgi?id=409379 – oberlies Jun 03 '13 at 08:23
  • related http://stackoverflow.com/questions/154314/when-should-one-use-final – Adriano Jul 18 '13 at 07:38

25 Answers25

208

I think it all has to do with good coding style. Of course you can write good, robust programs without using a lot of final modifiers anywhere, but when you think about it...

Adding final to all things which should not change simply narrows down the possibilities that you (or the next programmer, working on your code) will misinterpret or misuse the thought process which resulted in your code. At least it should ring some bells when they now want to change your previously immutable thing.

At first, it kind of looks awkward to see a lot of final keywords in your code, but pretty soon you'll stop noticing the word itself and will simply think, that-thing-will-never-change-from-this-point-on (you can take it from me ;-)

I think it's good practice. I am not using it all the time, but when I can and it makes sense to label something final I'll do it.

Johan Pelgrim
  • 6,033
  • 6
  • 37
  • 46
  • 18
    Instead of using the final keyword for parameters you can use static analysis tool such as FindBugs to require that parameter variables are not reassigned. This way you remove the syntactic burden and can enforce it via a FindBugs check in your Continuous integration tool. – Timo Westkämper May 16 '10 at 18:45
  • 23
    @Timo This would work, but it has the downside that this needs to be checked after checkin and not while the dev is working on the code. For `final`, the compiler obviously won't let you continue if you make a mistake. – Mike Aug 24 '10 at 18:00
  • 1
    @Mike, agreed. I love FindBugs and use it religiously, but when there's a language feature and compiler support... use it! Yeah, I think final all over the place is ugly, and when they finally do an incompatible Java rewrite, I hope everything is final by default. – andersoj Oct 20 '10 at 20:38
  • 10
    Eclipse has an option to add `final` whereever possible (variables that don't change) whenever you save. – Bert F Dec 10 '10 at 15:37
  • 25
    +1 I love `final`. It doesn't make a difference 98% of the time, it is a minor inconvenience %1 of the time, but the 1% of the time is saves me from doing something stupid or unintended is well worth it. – Bert F Dec 10 '10 at 15:40
  • here's a case where using final complicates your code... http://stackoverflow.com/questions/9350605/java-how-to-declare-final-a-variable-that-is-inialized-inside-a-try-catch-blo/9350647#comment11806864_9350647 – opensas Feb 19 '12 at 19:41
  • 14
    @BertF Yeah, I always let Eclipse add `final` modifiers everywhere when I "Clean Up..." my code. Everywhere means even in catch() blocks, and as said, you will not notice them after a while. Of course, if I would create a language, the `final` would be the default, and a `var` or `modifiable` would be the optional keyword. – Maarten Bodewes Mar 17 '12 at 13:30
  • @MaartenBodewes Funny, there's now a language running on the JVM where final is the default: [Kotlin](https://kotlinlang.org) – Joschua Jun 25 '16 at 22:09
  • @Joschua Trust me, I follow Kotlin with great interest. It still contains integer overflows and such, but otherwise it seems a step in the right direction. – Maarten Bodewes Jun 25 '16 at 22:47
  • "that-thing-will-never-change-from-this-point-on" too bad it doesn't work this way with mutable objects. – Dogcat Jul 08 '16 at 08:10
  • 1
    Especially when you're collaborating it's sooo useful! Often when I'm unsure what a variable/field does or if it's mutated somewhere I just slap a `final` in front of it and let the compiler figure it out :P If it compiles, awesome! Leave it in so it's easier to read for the next person. If not then at least you definitely know all the critical points where it's being used. – Daniel W. Aug 21 '17 at 15:48
205

Obsess over:

  • Final fields - Marking fields as final forces them to be set by end of construction, making that field reference immutable. This allows safe publication of fields and can avoid the need for synchronization on later reads. (Note that for an object reference, only the field reference is immutable - things that object reference refers to can still change and that affects the immutability.)
  • Final static fields - Although I use enums now for many of the cases where I used to use static final fields.

Consider but use judiciously:

  • Final classes - Framework/API design is the only case where I consider it.
  • Final methods - Basically same as final classes. If you're using template method patterns like crazy and marking stuff final, you're probably relying too much on inheritance and not enough on delegation.

Ignore unless feeling anal:

  • Method parameters and local variables - I RARELY do this largely because I'm lazy and I find it clutters the code. I will fully admit that marking parameters and local variables that I'm not going to modify is "righter". I wish it was the default. But it isn't and I find the code more difficult to understand with finals all over. If I'm in someone else's code, I'm not going to pull them out but if I'm writing new code I won't put them in. One exception is the case where you have to mark something final so you can access it from within an anonymous inner class.
Alex Miller
  • 69,183
  • 25
  • 122
  • 167
  • 5
    Most of the time when I see local variable without final word in front of it and it cannot be used there it tells me that I should probably extract some code in a new method that returns the desired value that I will make final. The cases where this is not applicable is when I use some streams or else that needs try-catching it. – nyxz Nov 07 '12 at 09:50
33

You really need to understand the full use of the final keyword before using it. It can apply to and has differing affects on variables, fields, methods and classes

I’d recommend checking out the article linked to below for more details.

Final Word On the final Keyword

maaartinus
  • 44,714
  • 32
  • 161
  • 320
HowardSP
  • 355
  • 2
  • 4
29

The final modifier, especially for variables, is a means to have the compiler enforce a convention that is generally sensible: make sure a (local or instance) variable is assigned exactly once (no more no less). By making sure a variable is definitely assigned before it is used, you can avoid common cases of a NullPointerException:

final FileInputStream in;
if(test)
  in = new FileInputStream("foo.txt");
else
  System.out.println("test failed");
in.read(); // Compiler error because variable 'in' might be unassigned

By preventing a variable from being assigned more than once, you discourage overbroad scoping. Instead of this:

 String msg = null;
 for(int i = 0; i < 10; i++) {
     msg = "We are at position " + i;
     System.out.println(msg);
 }
 msg = null;

You are encouraged to use this:

 for(int i = 0; i < 10; i++) {
     final String msg = "We are at position " + i;
     System.out.println(msg);
 }

Some links:

Bruno De Fraine
  • 45,466
  • 8
  • 54
  • 65
  • In short you can basically you can use `final` to [make Java more expression based](http://stackoverflow.com/a/18856192/318174). – Adam Gent Sep 17 '13 at 17:31
  • Actually "By making sure a variable is definitely assigned before it is used, you can avoid common cases of a NullPointerException:" this is not correct, 'final' makes no difference here, the compiler knows and complains about the 'in' variable possibly being null in the example provided. – nyholku Jan 29 '19 at 14:14
  • @nyholku You are right, in Java local variables must be definitely assigned before use, also without final. But for fields you need the final. In a slightly more complex example where "in" is an instance variable of a class, and the if/else is in the constructor, you need the final to signal the problem. Furthermore, also for local variables there is some value in final IMO, since it prevents the sloppy programmer from 'fixing' the compile error about "in" being possibly unassigned by adding "= null" to its declaration. In other words, final variables reduce uses of null, in my experience. – Bruno De Fraine Feb 01 '19 at 13:18
21

I'm pretty dogmatic about declaring every possible variable final. This includes method parameters, local variables, and rarely, value object fields. I've got three main reasons for declaring final variables everywhere:

  1. Declaring Intention: By declaring a final variable, I am stating that this variable is meant to be written to only once. It's a subtle hint to other developers, and a big hint to the compiler.
  2. Enforcing Single-use Variables: I believe in the idea that each variable should have only one purpose in life. By giving each variable only one purpose, you reduce the time it takes to grok the purpose of that particular variable while debugging.
  3. Allows for Optimization: I know that the compiler used to have performance enhancement tricks which relied specifically on the immutability of a variable reference. I like to think some of these old performance tricks (or new ones) will be used by the compiler.

However, I do think that final classes and methods are not nearly as useful as final variable references. The final keyword, when used with these declarations simply provide roadblocks to automated testing and the use of your code in ways that you could have never anticipated.

Ryan Ransford
  • 3,224
  • 28
  • 35
17

Effective Java has an item that says "Favour immutable objects". Declaring fields as final helps you take some small steps towards this, but there is of course much more to truly immutable objects than that.

If you know that objects are immutable they can be shared for reading among many threads/clients without synchronization worries, and it is easier to reason about how the program runs.

Lars Westergren
  • 2,119
  • 15
  • 25
  • 17
    careful - final and immutable are completely different concepts. Its easy to have a final mutable object - final is about the reference, mutability is about the object instance. final Person olaf = new Person(); olaf.setName("Olaf"); – Olaf Kock Sep 26 '08 at 12:04
  • 1
    Exactly-- immutable objects are one thing, immutable references (i.e. final) are something else entirely. – SCdF Sep 27 '08 at 06:01
  • 2
    But they are closely related since you can by declaring the Person.name field as final (and declaring the class final, and...) make the Person object final. It is however not as easy as just doing "final Person"... – Sebastian Ganslandt Sep 20 '09 at 18:50
  • This is also irrelevant for local variables (parameters are locals). It only applies to class variables so it only partially addresses the question. – Robin Sep 13 '11 at 14:56
13

I have never been in a situation where having a final keyword on a variable has stopped me from making a mistake, so for the moment I think it's a giant waste of time.

Unless there is a real reason for doing it (as in you want to make a specific point about that variable being final) I would rather not do it since I find it makes the code less readable.

If, however, you don't find it makes the code harder to read or longer to write then by all means go for it.

Edit: As a clarification (and an attempt to win back down-votes), I'm not saying don't mark constants as final, I'm saying don't do stuff like:

public String doSomething() {
  final String first = someReallyComplicatedExpressionToGetTheString();
  final String second = anotherReallyComplicatedExpressionToGetAnother();

  return first+second;
}

It just makes code (in my opinion) harder to read.

It's also worth remembering that all final does is prevent you from reassigning a variable, it doesn't make it immutable or anything like that.

SCdF
  • 57,260
  • 24
  • 77
  • 113
  • 1
    Turning the statement on its head: I have been in _plenty_ of situations where _not_ using `final` (and immutable objects in general) has had a significant contributing factor to the number and impact of bugs. – Chris Vest Sep 26 '08 at 09:22
  • 3
    I'm all for immutable objects, I just have never been in a situation where marking an immutable object final has helped me. – SCdF Sep 26 '08 at 21:49
  • 2
    I agree that we shouldn't use final on local variables and method parameters, it does make code much less readable. – rmaruszewski Mar 17 '10 at 08:29
  • @ChrisVest, maybe your functions are too long – Pacerier May 17 '20 at 13:31
8

Final should always be used for constants. It's even useful for short-lived variables (within a single method) when the rules for defining the variable are complicated.

For example:

final int foo;
if (a)
    foo = 1;
else if (b)
    foo = 2;
else if (c)
    foo = 3;
if (d)        // Compile error:  forgot the 'else'
    foo = 4;
else
    foo = -1;
David Leppik
  • 3,194
  • 29
  • 18
6

Sounds like one of the biggest argument against using the final keyword is that "it's unnecessary", and it "wastes space".

If we acknowledge the many benefits of "final" as pointed out by many great posts here, while admitting it takes more typing and space, I would argue that Java should have made variables "final" by default, and require that things be marked "mutable" if the coder wants it to be.

RAY
  • 6,810
  • 6
  • 40
  • 67
  • Seems strange to call it a variable then, doesn't it? – Alan Oct 31 '14 at 17:14
  • 2
    There are thousands of English words to choose from. – RAY Nov 07 '14 at 06:01
  • This is perfect. There are no arguments against `final` apart from "too long to write", "makes code clumsier". There are several arguments for `final`. And we can auto-add it on save, if you don't want to type it by hand. – Dmitriy Popov Apr 16 '20 at 12:08
5

I use final all the time for object attributes.

The final keyword has visibility semantics when used on object attributes. Basically, setting the value of a final object attribute happens-before the constructor returns. This means that as long as you don't let the this reference escape the constructor and you use final for all you attributes, your object is (under Java 5 semantics) guarenteed to be properly constructed, and since it is also immutable it can be safely published to other threads.

Immutable objects is not just about thread-safety. They also make it a lot easier to reason about the state transitions in your program, because the space of what can change is deliberately and, if used consistently, thoroughly limited to only the things that should change.

I sometimes also make methods final, but not as often. I seldomly make classes final. I generally do this because I have little need to. I generally don't use inheritance much. I prefer to use interfaces and object composition instead - this also lends itself to a design that I find is often easier to test. When you code to interfaces instead of concrete classes, then you don't need to use inheritance when you test, as it is, with frameworks such as jMock, much easier to create mock-objects with interfaces than it is with concrete classes.

I guess I should make the majority of my classes final, but I just haven't gotten into the habbit yet.

Chris Vest
  • 8,642
  • 3
  • 35
  • 43
5

I have to read a lot of code for my job. Missing final on instance variables is one of the top things to annoy me and makes understanding the code unnecessarily difficult. For my money, final on local variables causes more clutter than clarity. The language should have been designed to make that the default, but we have to live with the mistake. Sometimes it is useful particularly with loops and definite assignment with an if-else tree, but mostly it tends to indicate your method is too complicated.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
3

final should obviously be used on constants, and to enforce immutability, but there is another important use on methods.

Effective Java has a whole item on this (Item 15) pointing out the pitfalls of unintended inheritance. Effectively if you didn't design and document your class for inheritance, inheriting from it can give unexpected problems (the item gives a good example). The recommendation therefore is that you use final on any class and/or method that wasn't intended to be inherited from.

That may seem draconian, but it makes sense. If you are writing a class library for use by others then you don't want them inheriting from things that weren't designed for it - you will be locking yourself into a particular implementation of the class for back compatibility. If you are coding in a team there is nothing to stop another member of the team from removing the final if they really have to. But the keyword makes them think about what they are doing, and warns them that the class they are inheriting from wasn't designed for it, so they should be extra careful.

DJClayworth
  • 26,349
  • 9
  • 53
  • 79
3

Another caveat is that many people confuse final to mean that the contents of the instance variable cannot change, rather than that the reference cannot change.

Uri
  • 88,451
  • 51
  • 221
  • 321
2

Choosing to type final for each parameter in each method will produce so much irritation both for coders and code readers.

Once irritation goes beyond reasonable switch to Scala where arguments are final by default.

Or, you can always use code styling tools that will do that automatically for you. All IDEs have them implemented or as plugins.

Oleg Mikheev
  • 17,186
  • 14
  • 73
  • 95
2

Even for local variables, knowing that it is declared final means that I don't need to worry about the reference being changed later on. This means that when debugging and I see that variable later on, I am confident that it is referring to the same object. That is one less thing I need to worry about when looking for a bug. A bonus is that if 99% of variables are declared final, then the few variables which really are variable stand out better. Also, the final lets the compiler find some more possible stupid mistakes that might otherwise go unnoticed.

Diastrophism
  • 15,139
  • 1
  • 16
  • 7
1

Final when used with variables in Java provides a substitute for constant in C++. So when final and static is used for a variable it becomes immutable. At the same time makes migrated C++ programmers pretty happy ;-)

When used with reference variables it does not allow you to re-reference the object, though the object can be manipulated.

When final is used with a method, it does not allow the method to be over-ridden by the subclasses.

Once the usage is very clear it should be used with care. It mainly depends on the design as using final on the method would not help polymorphism.

One should only use it for variables when you are damn sure that the value of the variable will/should never be changed. Also ensure that you follow the coding convention encouraged by SUN.for eg: final int COLOR_RED = 1; (Upper case seperated by underscore)

With a reference variable, use it only when we need a an immutable reference to a particular object.

Regarding the readability part, ensue that comments play a very important role when using the final modifier.

Omnipotent
  • 27,619
  • 12
  • 30
  • 34
  • It's probably because you state that you should ONLY make it final when XYZ. Others consider it better practice to make EVERYTHING final unless there is a need to do so otherwise. – Tim Frey Sep 30 '08 at 18:46
  • 1
    It is not at all a substitute for C++ const keyword. -1. – tmj Jun 02 '16 at 09:37
1

I never use them on local variables, there is little point for the added verbosity. Even if you don't think the variable should be reassigned, that will make little difference to the next person altering that code that thinks otherwise, and since the code is being changed, any original purpose for making it final may no longer be valid. If it is just for clarity, I believe it fails due to the negative effects of the verbosity.

Pretty much the same applies to member variables as well, as they provide little benefit, except for the case of constants.

It also has no bearing on immutability, as the best indicator of something being immutable is that it is documented as such and/or has no methods that can alter the object (this, along with making the class final is the only way to guarantee that it is immutable).

But hey, that's just my opinion :-)

Robin
  • 24,062
  • 5
  • 49
  • 58
1

I set up Eclipse to add final on all fields and attributes which are not modified. This works great using the Eclipse "save actions" which adds these final modifiers (among other things) when saving the file.

Highly recommended.

Check out my blog post of Eclipse Save Actions.

zvikico
  • 9,765
  • 4
  • 38
  • 49
1

For arguments I'm think they're not needed. Mostley they just hurt readabillity. Rreassigning an argument variable is so insanely stupid that I should be pretty confident that they can be treated as constants anyway.

The fact that Eclipse colors final red makes it easier to spot variable declarations in the code which I think improves readbillity most of the time.

I try to enforce the rule that any and all variables should be final it there isn't an extremley valid reason not to. It's so much easier to answer the "what is this variable?" question if you just have to find the initilization and be confident that that is it.

I actually get rather nervous around non-final variables now a days. It's like the differnce between having a knife hanging in a thread abouve your head, or just having it you kitchen drawer...

A final variable is just a nice way to lable values.

A non-final variable is bound to part of some bug-prone algorithm.

One nice feature is that when the option to use a variable in out of the question for an algorithm most of the time the sollution is to write a method instead, which usually improves the code significantly.

John Nilsson
  • 17,001
  • 8
  • 32
  • 42
1

I've been coding for a while now and using final whenever I can. After doing this for a while (for variables, method parameters and class attributes), I can say that 90% (or more) of my variables are actually final. I think the benefit of NOT having variables modified when you don't want to (I saw that before and it's a pain sometimes) pays for the extra typing and the extra "final" keywords in your code.

That being said, if I would design a language, I would make every variable final unless modified by some other keyword.

I don't use final a lot for classes and methods, thought. This is a more or less complicated design choice, unless your class is a utility class (in which case you should have only one private constructor).

I also use Collections.unmodifiable... to create unmodifiable lists when I need to.

Ravi Wallau
  • 10,416
  • 2
  • 25
  • 34
0

I hardly use final on methods or classes because I like allowing people to override them.

Otherwise, I only use finally if it is a public/private static final type SOME_CONSTANT;

jjnguy
  • 136,852
  • 53
  • 295
  • 323
0

Using anonymous local classes for event listeners and such is a common pattern in Java. The most common use of the final keyword is to make sure that variables in scope are accessible to the even listener.

However, if you find yourself being required to put a lot of final statements in your code. That might be a good hint you're doing something wrong.

The article posted above gives this example:

public void doSomething(int i, int j) {
    final int n = i + j; // must be declared final

    Comparator comp = new Comparator() {
        public int compare(Object left, Object right) {
            return n; // return copy of a local variable
        }
    };
}
Hans Sjunnesson
  • 21,745
  • 17
  • 54
  • 63
0

I use it for constants inside and outside methods.

I only sometimes use it for methods because I don't know if a subclass would NOT want to override a given method(for whatever reasons).

As far as classes, only for some infrastructure classes, have I used final class.

IntelliJ IDEA warns you if a function parameter is written to inside a function. So, I've stopped using final for function arguments. I don't see them inside java Runtime library as well.

anjanb
  • 12,999
  • 18
  • 77
  • 106
0

Marking the class final can also make some method bindings happen at compile time instead of runtime. Consider "v2.foo()" below - the compiler knows that B cannot have a subclass, so foo() cannot be overridden so the implementation to call is known at compile time. If class B is NOT marked final, then it's possible that the actual type of v2 is some class that extends B and overrides foo().

class A {
    void foo() {
        //do something
    }
}
final class B extends A {
    void foo() {
    }
}
class Test {
    public void t(A v1, B v2) {
        v1.foo();
        v2.foo();
    }
}
Eugene
  • 826
  • 1
  • 7
  • 7
-1

Using final for constants is strongly encouraged. However, I wouldn't use it for methods or classes (or at least think about it for a while), because it makes testing harder, if not impossible. If you absolutely must make a class or method final, make sure this class implements some interface, so you can have a mock implementing the same interface.

Paweł Hajdan
  • 18,074
  • 9
  • 49
  • 65