Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should one use final for method parameters and local variables?

Tags:

java

final

People also ask

Can final be used on method parameters and local variables?

In Java, you can qualify local variables and method parameters with the final keyword. Doing so results in not being able to reassign x and qwerty in the body of the method.

Why should method parameters be final?

Having final on methods parameters helps you understand the outgoings of the method at first glance, and draws some attention to those non-final parameters.

When should variables be final?

The term effectively final variable was introduced in Java 8. A variable is effectively final if it isn't explicitly declared final but its value is never changed after initialization.

Should local variables be final?

final is the only allowed access modifier for local variables. final local variable is not required to be initialized during declaration. final local variable allows compiler to generate an optimized code. final local variable can be used by anonymous inner class or in anonymous methods.


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.

  • Edit: note that one use case where final local variables are actually very useful as mentioned by @adam-gent is when value gets assigned to the var in the if/else branches.


Is it something I should make an effort to remember to do?

No, if you are using Eclipse, because you can configure a Save Action to automatically add these final modifiers for you. Then you get the benefits for less effort.


The development-time benefits of "final" are at least as significant as the run-time benefits. It tells future editors of the code something about your intentions.

Marking a class "final" indicates that you've not made an effort during design or implementation of the class to handle extension gracefully. If the readers can make changes to the class, and want to remove the "final" modifier, they can do so at their own risk. It's up to them to make sure the class will handle extension well.

Marking a variable "final" (and assigning it in the constructor) is useful with dependency injection. It indicates the "collaborator" nature of the variable.

Marking a method "final" is useful in abstract classes. It clearly delineates where the extension points are.


I use final all the time to make Java more expression based. See Java's conditions (if,else,switch) are not expression based which I have always hated especially if your used to functional programming (ie ML, Scala or Lisp).

Thus you should try to always (IMHO) use final variables when using conditions.

Let me give you an example:

    final String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
        default:
            throw new IllegalStateException();
    }

Now If add another case statement and do not set name the compiler will fail. The compiler will also fail if you do not break on every case (that you set the variable). This allows you to make Java very similar to Lisp's let expressions and makes it so your code is not massively indented (because of lexical scoping variables).

And as @Recurse noted (but apparently -1 me) you can do the preceding with out making String name final to get the compiler error (which I never said you couldn't) but you could easily make the compiler error go away setting name after the switch statement which throws away the expression semantics or worse forgetting to break which you cannot cause an error (despite what @Recurse says) without using final:

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            //break; whoops forgot break.. 
            //this will cause a compile error for final ;P @Recurse
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

Because of the bug setting name (besides forgetting to break which also another bug) I can now accidentally do this:

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        //should have handled all the cases for pluginType
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

The final variable forces a single evaluation of what name should be. Similar to how a function that has a return value must always return a value (ignoring exceptions) the name switch block will have to resolve name and thus bound to that switch block which makes refactoring chunks of code easier (ie Eclipe refactor: extract method).

The above in OCaml:

type plugin = CandidateExport | JobPostingImport

let p = CandidateExport

let name = match p with
    | CandidateExport -> "Candidate Stuff"
    | JobPostingImport -> "Blah" ;;

The match ... with ... evaluates like a function ie expression. Notice how it looks like our switch statement.

Here is an example in Scheme (Racket or Chicken):

(define name 
    (match b
      ['CandidateExport "Candidate Stuff"]
      ['JobPostingImport "Blah"]))

Well, this all depends on your style... if you LIKE seeing the final when you won't be modifying the variable, then use it. If you DON'T LIKE seeing it... then leave it out.

I personally like as little verbosity as possible, so I tend to avoid using extra keywords that aren't really necessary.

I prefer dynamic languages though, so it's probably no surprise I like to avoid verbosity.

So, I would say just pick the direction you are leaning towards and just go with it (whatever the case, try to be consistent).


As a side note, I have worked on projects that both use and don't use such a pattern, and I have seen no difference in the amount of bugs or errors... I don't think it is a pattern that will hugely improve your bug count or anything, but again it is style, and if you like expressing the intent that you won't modify it, then go ahead and use it.


I've found marking method parameters and locals as final is useful as a refactoring aid when the method in question is an incomprehensible mess several pages long. Sprinkle final liberally, see what "cannot assign to final variable" errors the compiler (or your IDE) throws up, and you just might discover why the variable called "data" ends up null even though several (out of date) comments swear that can't happen.

Then you can fix some of the errors by replacing the reused variables with new variables declared closer to the point of use. Then you find you can wrap whole parts of the method in scoping braces, and suddenly you're one IDE keypress away from "Extract Method" and your monster just got more comprehensible.

If your method is not already an unmaintainable wreck, I guess there might be value in making stuff final to discourage people from turning it into said wreck; but if it's a short method (see: not unmaintainable) then you risk adding a lot of verbosity. In particular, Java function signatures are hard enough to fit into 80 characters as it is without adding six more per argument!


It is useful in parameters to avoid change the parameter value by accident and introduce a subtle bug. I use to ignore this recommendation but after spending some 4 hrs. in a horrible method ( with hundreds of lines of code and multiple fors, nested ifs and all sort of bad practices ) I would recommend you to do it.

 public int processSomethingCritical( final int x, final int y ){
 // hundreds of lines here 
     // for loop here...
         int x2 = 0;
        x++; // bug aarrgg...
 // hundreds of lines there
 // if( x == 0 ) { ...

 }

Of course in a perfect world this wouldn't happen, but.. well.. sometimes you have to support others code. :(