Why Would One Mark Local Variables and Method Parameters as "Final" in Java

Why would one mark local variables and method parameters as final in Java?

You should try to do this, whenever it is appropriate. Besides serving to warn you when you "accidentally" try to modify a value, it provides information to the compiler that can lead to better optimization of the class file. This is one of the points in the book, "Hardcore Java" by Robert Simmons, Jr. In fact, the book spends all of its second chapter on the use of final to promote optimizations and prevent logic errors. Static analysis tools such as PMD and the built-in SA of Eclipse flag these sorts of cases for this reason.

Use of final local variables in java

Firstly, the part about variables being "overridden" - final has two very different meanings. For classes and methods, it's about inheritance; for variables it's about being read-only.

There's one important "feature" of final local variables: they can be used in local (typically anonymous) inner classes. Non-final local variables can't be. That's the primary use of final for local variables, in my experience.

public void foo() {
final String x = "hello";
String y = "there";

Runnable runnable = new Runnable() {
@Override public void run() {
System.out.println(x); // This is valid
System.out.println(y); // This is not
}
};
runnable.run();
}

Note that as a matter of style, some people like to use final even when they're not capturing the variable in a local inner class. I'd certainly be comfortable with final being the default, but a different modifier for "non-final", but I find that adding the modifier explicitly everywhere is too distracting.

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

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 there any performance reason to declare method parameters final in Java?

The final keyword does not appear in the class file for local variables and parameters, thus it cannot impact the runtime performance. It's only use is to clarify the coders intent that the variable not be changed (which many consider dubious reason for its usage), and dealing with anonymous inner classes.

There is a lot of argument over whether the final modifier on the method itself has any performance gain since the methods will be inlined by the optimizing compiler at runtime anyway, regardless of the modifier. In this case it should also only be used to restrict the overriding of the method.

final keyword in method parameters

Java always makes a copy of parameters before sending them to methods. This means the final doesn't mean any difference for the calling code. This only means that inside the method the variables can not be reassigned.

Note that if you have a final object, you can still change the attributes of the object. This is because objects in Java really are pointers to objects. And only the pointer is copied (and will be final in your method), not the actual object.

Why is it considered good practice to mark method parameters as final?

If you mark a method parameter as final, you can't modify the parameter's value within the scope of the method:

public void xyz(final String parameter) {
parameter = "..." //compiler error!
}

Understand that the value of parameter is the reference to the object passed to the method, and not the value of the object itself.

By marking the method parameter as final, the compiler will throw an error upon compilation. This serves as a reminder that you should not modify the value of the parameter within your method.

It's considered a bad practice to modify the original parameter within your method.[1]

If the value of the parameter can change to reference another object, it might not be immediately clear what object is being referenced at any given point within the body of your method.

Consider the following:

public void xyz(String parameter) {
//Complicated logic that might span 20-30 lines.

parameter = "Joe";

//More complicated logic that might span a few lines.

//New logic being added that needs reference to the value of the parameter.
}

In a complicated method, like above, it might be difficult for a programmer to identify what object parameter references. Furthermore, if the programmer needs a reference to parameter he no longer has one.



  1. Is it a good practice to change arguments in Java


Related Topics



Leave a reply



Submit