116

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 ....
}
lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
John
  • 2,682
  • 5
  • 23
  • 24
  • 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. – Peter Lawrey Nov 12 '10 at 08:54
  • 1
    Possible duplicate of [Why should I use the keyword "final" on a method parameter in Java?](https://stackoverflow.com/questions/500508/why-should-i-use-the-keyword-final-on-a-method-parameter-in-java) – james.garriss Oct 10 '17 at 18:37
  • 2
    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. – Sid Sep 16 '18 at 05:15

11 Answers11

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();
    }
iajrz
  • 749
  • 7
  • 16
PeterMmm
  • 24,152
  • 13
  • 73
  • 111
  • 32
    +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.) – Donal Fellows Nov 12 '10 at 09:22
  • 3
    May I ask the reasoning behind this ? – KodeWarrior Jan 18 '14 at 15:42
  • 25
    No more necessary with Java 8. – Amit Parashar Nov 05 '15 at 07:57
  • So with java 8 you can access from an inner class without it being final? – simgineer Feb 16 '18 at 01:07
  • 3
    @simgineer read here: https://stackoverflow.com/questions/28408109/java-stopped-erroring-on-non-final-variables-in-inner-classes-java-8 – PeterMmm Feb 17 '18 at 08:54
  • 5
    @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_ :) – varun Apr 09 '19 at 18:33
  • @varun agreed +1 – Amit Parashar Apr 10 '19 at 18:07
  • @KodeWarrior I know it is a little late, but the reasoning behind is the concept of `closure`s. – mcy Oct 05 '21 at 06:43
43

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.

Community
  • 1
  • 1
pgras
  • 12,614
  • 4
  • 38
  • 46
  • 21
    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. – Rob Grant Aug 15 '14 at 09:58
41

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;
}
djna
  • 54,992
  • 14
  • 74
  • 117
  • 1
    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. – JoseHdez_2 Dec 21 '18 at 10:54
  • 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 Feb 14 '23 at 20:01
  • @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. – djna Feb 15 '23 at 13:15
14

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.

Adrian Pronk
  • 13,486
  • 7
  • 36
  • 60
4

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.

Sid
  • 4,893
  • 14
  • 55
  • 110
  • 1
    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. – Sam003 Jul 23 '15 at 00:08
  • 2
    Immutability is always a desirable trait. Java does not have it out of the box. Making variables final at least ensures reference integrity. – Sid Jul 23 '15 at 16:29
  • 1
    I agree. But if we really want to achieve immutability for objects, we could try make a deep clone. – Sam003 Jul 23 '15 at 17:21
  • 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. – Agustí Sánchez Jan 29 '22 at 01:19
  • An immutable reference is the first step towards immutability. – Sid Jan 29 '22 at 06:28
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.

dimitrisli
  • 20,895
  • 12
  • 59
  • 63
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.

Community
  • 1
  • 1
1

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

Witold Kaczurba
  • 9,845
  • 3
  • 58
  • 67
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.

madhurtanwani
  • 1,199
  • 7
  • 13
0

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.

RAY
  • 6,810
  • 6
  • 40
  • 67
-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.

Community
  • 1
  • 1
Kamal
  • 3,878
  • 4
  • 21
  • 24
  • 6
    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. – Flo Jun 30 '13 at 06:55