Final Modifier for method arguments. What do you think?

The IT industry today is sodden with TLAs like SOA, ESB… and FLAs like AJAX, SOAP and JUNK. i was thinking about refreshing myself with some fundamentals again. Blogging about a basic concept may not be cool, but refreshing – don’t you think? I know what you are thinking. You are thinking that i am digressing too much. Ok, lets cut to the chase.

One of the best practices i follow religiously is to use final modifiers for method arguments where applicable. This is “supposedly” a best-practice written by somebody somewhere. Regardless of whether it is documented as a best-practice or not it is an important concept to understand and use. I have 2 valid reasons to use them for my method arguments.

First, final variables cannot be modified. Come on, everybody knows that. Maybe, but its use is significantly enhanced when it is a method argument and more importantly when you are in a big team environment.

Lets assume that a method takes List as its argument. Typically, the intention of that method is to work with the List – add to it, remove elements from it, use its elements in some way, sort it and what not. Consequently when the method returns, the caller can investigate the passed List and work with the modifications the callee introduced. But the caller will be on for a big surprise if the callee changes the instance that reference points to itself.

We know that java uses “Pass by copy of reference”. If the callee points the received reference to a different List and then modifies this List, the caller will not be able to see any change at all. This is because the copy of the reference held by the caller still points to the same old List. More often than not this is done by mistake and is not intentional. If such a behavior is intentional, final modifier is not required. In all other cases since this leads to bugs in code, it is a good practice to use final modifier for method arguments.

Second, if the method uses the infamous anonymous inner-class syntax to do something, and that inner class wants to use the methods arguments, java requires those arguments to be declared final. This is more of a rule than a valid reason.

Are there more valid reasons? I will be glad to receive information from you guys.

Ganeshji Marwaha

I spend my days as the Director of Technology for Mobility practice and help my clients design enterprise and consumer mobile strategies. Mobile Payments, Digital Wallet and Tokenization technologies are my areas of specialization

  • The final keyword on a method parameter does not affect the caller of a method in any way whatsoever.

    All a final method parameter enforces is that the method itself does not modify the reference. But, it makes no guarantee that methods or fields of that parameter will not be changed. So a final List can still be modified, and those changes will be reflected in the caller’s reference, just as with a non-final parameter.

  • Ganeshji Marwaha

    @Craig: Thats exactly the point I am trying to make. If the caller expects the lists data to modified, but the callee mistakenly assigns the argument to a new List, then whatever modifications the callee makes to the List will not be visible to the caller.

  • Ah, that makes sense. I thought you were trying to indicate that making a parameter final ensured that a caller would not see any changes made to a passed-in object (like const in C++).

  • Vinod

    Here is some sample code to illustrate the problem better.

    public static void main(String[] args) {
    ArrayList> l = new ArrayList>();
    l.add(“1”);
    l.add(“2”);
    l.add(“3”);
    System.out.println(“Original List ” + l);
    badtamper(l);
    System.out.println(“In caller value after bad callee:” + l);
    tamperlist(l);
    System.out.println(“In caller value :” + l);
    }

    private static void badtamper(final ArrayList> l) {
    ArrayList> nl = new ArrayList>();
    nl.add(“One”);
    nl.add(“Two”);
    nl.add(“Three”);
    l = nl;
    System.out.println(“In bad callee value :” + l);
    }

    private static void tamperlist(ArrayList> l) {
    l.remove(2);
    l.add(2, “two”);
    System.out.println(“In callee value :” + l);
    }

    Now when the code is run the following gets printed out :
    Original List [1, 2, 3]
    In bad callee value :[One, Two, Three]
    In caller value after bad callee:[1, 2, 3]
    In callee value :[1, 2, two]
    In caller value :[1, 2, two]

    And looking at the values, the problem becomes obvious.
    To prevent it, if ‘final’ arguments are used then the editor can warn when an assignment is done for the variable that has been passed and thus prevent the unpleasant surprise, which most developers go thru in their learning curve and learn the hard way.

  • Ganeshji Marwaha

    @Vinod: Good Illustration of the problem with the example.

  • You should only introduce additional syntactic clutter if it solves problems. I love to make object fields final because I do a lot of concurrent programming.

    But making local variables final is solving a problem I haven’t seen happening.

    If in Java by default all local variables where final and you need to do something special to mark them as updatable, I would not have a problem with it. But adding it to each variable explicitly makes code very verbose.

    And it even gets more verbose if annotations are added.. like the @NotNull crap.

  • Steve

    “If the caller expects the lists data to modified, but the callee mistakenly assigns the argument to a new List, then whatever modifications the callee makes to the List will not be visible to the caller.”

    This tells me that the method is not being unit tested, syntactic changes will not change that and will not fix other bugs unit testing will also expose.

    Personally I think the params should be final by default and I would reject code I review that modifies params as I have yet to see a case where it is justified.

  • musk

    @Steve It is a bad idea to use a unit test for something that the compiler can catch for you. If you do not rely on the compiler for finding potential bugs for you then why are you even using a statically typed language in the first place?

  • Imho a signature may be more clear while using the final keyword for parameters, but methods should not be so long that we cannot infer the immutability of a parameter by reading the method body.

  • Shogg

    +1 Peter Veentjer’s final members and non-final locals where possible
    +1 Steve’s not to reassign params (locals)

    As stated in the article, the ‘final’ keyword is necassary to mark parameters as ‘semi-output’ parameters. The usual way to return a result in Java is to use a ‘return’ statement. So there shouldn’t be many ‘final’ parameters in Java code.

    Java is missing real output parameters. C# has it’s ref- and out-parameters. You can reassign them in the callee and the caller will notice it because these parameters are references(-of-references).

  • Good job man..

  • Pingback: Code Goop()

  • Sjoerd Talsma

    I fully agree with Peter Veentjer, with the addition that I think the lack of named parameters in Java is totally unrelated but similar problem.

  • I prefer to omit ‘final’ from method arguments, and use tools like Checkstyle to enforce rules such as not changing what method arguments refer to. Too much syntactic noise for my taste.

  • Eric Jablow

    Final parameters and local variables can be used in inner classes. Non-final parameters and local variables cannot. Whether this is good or bad is arguable.

  • Jimmy

    l = nl;

    Using final to clutter up your code in an attempt to prevent lines like this is pure rubbish. If you are working for/with developers who make such rudimentary mistakes such as this I suggest you fire them or switch jobs.

    If you really need a compiler to prevent you from making such mistakes you really have much bigger problems than finals. It’s absolutely pointless in java

  • travmik

    So guys.
    Vinod get us example and Ganeshji Marwaha says that it is good code, but lets look at the code.

    private static void badtamper(final ArrayList l) {
    ArrayList nl = new ArrayList();
    nl.add(”One”);
    nl.add(”Two”);
    nl.add(”Three”);
    l = nl; – THIS IS COMPILATION TIME ERROR – you can’t change reference if it is final, but you can change data in object
    System.out.println(”In bad callee value :” + l);
    }

    Ok i can change some things:

    public static void main(String[] args) {
    ArrayList l = new ArrayList();
    l.add(”1?);
    l.add(”2?);
    l.add(”3?);
    System.out.println(”Original List ” + l);
    badtamper(l);
    System.out.println(”In caller value after bad callee:” + l);
    tamperlist(l);
    System.out.println(”In caller value :” + l);
    }

    private static void badtamper(final ArrayList l) {
    l.remove(2);
    l.add(2, “bad”);
    System.out.println(”In bad callee value :” + l);
    }

    private static void tamperlist(ArrayList> l) {
    l.remove(2);
    l.add(2, “not bad”);
    System.out.println(”In callee value :” + l);
    }

    Now when the code is run the following gets printed out :
    Original List [1, 2, 3]
    In bad callee value :[1, 2, bad]
    In caller value after bad callee:[1, 2, bad]
    In callee value :[1, 2, not bad]
    In caller value :[1, 2, not bad]

    Actually no difference. 😉

  • Pingback: non const()

  • Consequently when the method returns, the caller can investigate the passed List and work with the modifications the callee introduced.

  • you are great to do this for us, thank you very much, you can have a look at the ghd and chi hair straighteners.

  • Great informative article! Thanks so much for sharing your wealth of information.

  • you are great to do this for us, thank you very much, you can have a look at the ghd and chi hair straighteners.

  • I ran across this blog post. It’s about how the final modifier is used for method parameters. A sample of what the post is trying to convey look…

  • I’m so glad to have found your web page. My pal mentioned it to me before, yet never got around to checking it out until now. I must express, I’m floored. I really enjoyed reading through your posts and will absolutely be back to get more.

  • Thanks you give me great information about method argument the required arguments get assigned the value that corresponds to their order in the argument list while the optional argument gets all the values that are left over that correspond to it’s order.

  • Don’t make friends who are comfortable to be with. Make friends who will force you to lever yourself up.