121

What difference that final makes between the code below. Is there any advantage in declaring the arguments as final.

public String changeTimezone( Timestamp stamp, Timezone fTz, Timezone toTz){ return .... } public String changeTimezone(final Timestamp stamp, final Timezone fTz, final Timezone toTz){ return .... } 
5
  • 6
    There are code analysers which warn if a parameter is re-used or reassigned. (Same for local variables) IMHO, This is a better way to catch such parameters if you find changing them is undesireable. Commented Nov 12, 2010 at 8:54
  • 2
    Possible duplicate of Why should I use the keyword "final" on a method parameter in Java? Commented Oct 10, 2017 at 18:37
  • 3
    I feel Java should make all input method arguments as final by default. And then if I want to modify the reference, I would have to do it manually. That way, guilt factor would prevent many such cases. Commented Sep 16, 2018 at 5:15
  • @PeterLawrey Why do you prefer this to be done by a third party code analyzer instead of as a programming language feature? Being a programming language feature has the benefit that everyone who modifies and compiles the code can see and use the enforcement of this. I can see a code analyser being useful (in addition) to also apply to local variables and to enforce this for the whole code base without having to remember putting final or alternatively ensuring final is put there. Commented Jul 15, 2024 at 16:48
  • @xuiqzy my preference would have been that arguments were final by default in the language and only non final with a keyword. However that is unlikely to change. Commented Jul 16, 2024 at 19:17

11 Answers 11

145

As a formal method parameter is a local variable, you can access them from inner anonymous classes only if they are declared as final.

This saves you from declaring another local final variable in the method body:

 void m(final int param) { new Thread(new Runnable() { public void run() { System.err.println(param); } }).start(); } 
Sign up to request clarification or add additional context in comments.

9 Comments

+1: This is an important use case, and the only time when you need it. (The rest of the time it's just a matter of what's convenient for helping the programmer.)
May I ask the reasoning behind this ?
No more necessary with Java 8.
@AmitParashar True, but Java 8 is just saving you from having to use the keyword "final" every time you have to use the variable in an inner class... The reality is that the compiler is merely making the finality implicit, you still need the variable to be effectively final... So, you still get a compile time error in case you try to assign to it later! Java 8: SNEAK 100 :)
|
44

Extract from The final word on the final keyword

Final Parameters

The following sample declares final parameters:

public void doSomething(final int i, final int j) { // cannot change the value of i or j here... // any change would be visible only inside the method... } 

final is used here to ensure the two indexes i and j won't accidentally be reset by the method. It's a handy way to protect against an insidious bug that erroneously changes the value of your parameters. Generally speaking, short methods are a better way to protect from this class of errors, but final parameters can be a useful addition to your coding style.

Note that final parameters are not considered part of the method signature, and are ignored by the compiler when resolving method calls. Parameters can be declared final (or not) with no influence on how the method is overriden.

2 Comments

Might be better to use objects rather than primitives for this example, as primitive changes will always only be visible inside the method. And in the case of objects, you can still change them. You just can't point at a new object. In fact now I think about it, final doesn't really change anything compared to leaving it out, other than saving a variable declaration with AICs and having the compiler point out accidental modifications of parameters that you didn't want to modify for some reason.
@RobGrant Preventing accidental modifications of paramaters is in fact an important and useful feature in itself. Many coding styles avoid modifications of variables (not only parameters) to make code easier to reason about. For this exact reason, many programming languages have the concept of declaring variables as not being able to be reassigned to enforce this in the language. E.g. the const versus the let in javascript. For a great explanation of why this is often a desirable coding style, see the answer of RAY on Nov 12, 2020 at 9:39: stackoverflow.com/a/4163275/4288004
44

The final prevents you from assigning a new value to the variable, and this can be helpful in catching typos. Stylistically you might like to keep the parameters received unchanged and assign only to local variables, so final would help to enforce that style.

Must admit I rarely remember to use final for parameters, maybe I should.

public int example(final int basicRate){ int discountRate; discountRate = basicRate - 10; // ... lots of code here if ( isGoldCustomer ) { basicRate--; // typo, we intended to say discountRate--, final catches this } // ... more code here return discountRate; } 

5 Comments

Great example of how declaring arguments as final can be useful. I'm partial to this but they're also a mouthful for 3+ parameters.
Great example of alternative ways to achieve same code quality-assurance: unit-tests. Since the mistake modifies an output this mistake or typo should or would have been caught in a unit-test.
@hc_dev I don't see this as an alternative, more a complement; a way to make code intention clear. We still need all the unit tests.
This is basically a way to make a variable constant like for example the const in javascript, so to forbid assigning something else to it after it gets its value. Just that final is restricted to be applied to parameters and fields. Restricting the assignment of a new value to a variable is a common concept in many programming languages that helps to enforce a coding style and/or prevent accidental reassignment.
The enforcement of that also helps readers rely on the fact that it's not reassigned. For a great explanation of why this is often a desirable coding style, see the answer of RAY on Nov 12, 2020 at 9:39: stackoverflow.com/a/4163275/4288004
15

It doesn't make a lot of difference. It just means that you can't write:

stamp = null; fTz = new ...; 

but you can still write:

stamp.setXXX(...); fTz.setXXX(...); 

It's mainly a hint to the maintenance programmer that follows you that you aren't going to assign a new value to the parameter somewhere in the middle of your method where it isn't obvious and might therefore cause confusion.

1 Comment

Also, there are many programming languages that have the concept of declaring variables as not being able to be reassigned for this exact reason. E.g. the const versus the let in javascript. For a great explanation of why this is often a desirable coding style, see the answer of RAY on Nov 12, 2020 at 9:39: stackoverflow.com/a/4163275/4288004
5

The final keyword when used for parameters/variables in Java marks the reference as final. In case of passing an object to another method, the system creates a copy of the reference variable and passes it to the method. By marking the new references final, you protect them from reassignment. It's considered sometimes a good coding practice.

6 Comments

I have to add something: if parameters are primitive, I don't see any differences. Besides, if parameters are Collections(a list of objects...), adding final could not prevent them being modified.
Immutability is always a desirable trait. Java does not have it out of the box. Making variables final at least ensures reference integrity.
I agree. But if we really want to achieve immutability for objects, we could try make a deep clone.
final does not help with immutability at all. The changes to primitive values are lost outside the method scope whether the parameter is marked as final or not. Changes to mutable objects are propagated outside the scope whether the parameter is marked as final or not. "Useless" is the word that comes to my mind.
An immutable reference is the first step towards immutability.
|
4

For the body of this method the final keyword will prevent the argument references to be accidentally reassigned giving a compile error on those cases (most IDEs will complain straight away). Some may argue that using final in general whenever possible will speed things up but that's not the case in recent JVMs.

Comments

4

Two advantages that I see are listed :

1 Marking the method argument as final prevents reassignment of the argument inside the method

From you example

 public String changeTimezone(final Timestamp stamp, final Timezone fTz, final Timezone toTz){ // THIS WILL CAUSE COMPILATION ERROR as fTz is marked as final argument fTz = Calendar.getInstance().getTimeZone(); return .. } 

In a complicated method marking the arguments as final will help in accidental interpretation of these arguments as methods local variables and reassigning as compiler will flag these cases as shown in the example.

2 Passing the argument to an anonymous inner class

As a formal method parameter is a local variable, you can access them from inner anonymous classes only if they are declared as final.

1 Comment

Regarding point 1: There are many programming languages that have the concept of declaring variables as not being able to be reassigned because reassignment is often confusing and it's nice to enforce against it in the language. E.g. the const versus the let in javascript. For a great explanation of why this is often a desirable coding style, see the answer of RAY on Nov 12, 2020 at 9:39: stackoverflow.com/a/4163275/4288004
2

I'm speaking of marking variables and fields final in general - doesn't just apply to method arguments. (Marking methods/classes final is a whole different thing).

It's a favor to the readers/future maintainers of your code. Together with a sensible name of the variable, it's helpful and reassuring to the reader of your code to see/understand what the variables in question represent - and it's reassuring to the reader that whenever you see the variable in the same scope, the meaning stays the same, so (s)he doesn't have to scratch his head to always figure out what a variable means in every context. We've seen too many abuses of "re-use" of variables, that makes even a short code snippet hard to understand.

1 Comment

Exactly, great explanation! Also, there are many programming languages that have the concept of declaring variables as not being able to be reassigned for this exact reason. E.g. the const versus the let in javascript.
0

Its just a construct in Java to help you define a contract and stick to it. A similar discussion here : http://c2.com/cgi/wiki?JavaFinalConsideredEvil

BTW - (as the twiki says), marking args as final is generally redundant if you are following good programming principles and hance done reassign / redefine the incoming argument reference.

In the worst case, if you do redefine the args reference, its not going to affect the actual value passed to the function - since only a reference was passed.

1 Comment

If you really follow the principle of not reassigning the arguments, then the final would be the proper way to convey to the reader that they can rely on this fact, so it would make the code easier to read because they now know that they don't need to keep track of the value of this variable but that it always has the value it had when it was passed in. The final also helps to enforce this practice and avoid accidentally not following it or even mistyping which variable to override and thus not following it.
0

- In the past (before Java 8 :-) )

Explit use of "final" keyword affected accessibility of the method variable for internal anonymous classes.

- In modern (Java 8+) lanaguage there is no need for such usage:

Java introduced "effectively final" variables. Local variables and method paramters are assummed final if the code does not imply changing of value of the variable. So if you see such keyword in Java8+ you can assume it is unecessary. Introduction of "effectively final" makes us type less code when using lambdas.

1 Comment

This is not the only use case! Marking a variable in code as forbidden from reassignment (such as e.g. const in javascript) has the use of enforcing that code avoids reassigning variables. This can often make code easier to read and reason about, preventing subtle bugs. See answer of RAY on Nov 12, 2020 at 9:39: stackoverflow.com/a/4163275/4288004
-3

The final keyword prevents you from assigning a new value to the parameter. I would like to explain this with a simple example

Suppose we have a method

method1(){

Date dateOfBirth =new Date("1/1/2009");

method2(dateOfBirth);

method3(dateOfBirth); }

public mehod2(Date dateOfBirth) {
....
....
....
}

public mehod2(Date dateOfBirth) {
....
....
....
}

In the above case if the "dateOfBirth" is assigned new value in method2 than this would result in the wrong output from method3. As the value that is being passed to method3 is not what it was before being passed to method2. So to avoid this final keyword is used for parameters.

And this is also one of the Java Coding Best Practices.

1 Comment

That is not quite right. Even if the argument dateOfBirth is changed to another value in method2() this would have no effect on method2(), since Java passes by value and not by reference.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.