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.
Answer from Thirler on Stack OverflowJava 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.
There is a circumstance where you're required to declare it final —otherwise it will result in compile error—, namely passing them through into an anonymous class or a lambda. Here's a basic example using an anonymous class:
public FileFilter createFileExtensionFilter(final String extension) {
FileFilter fileFilter = new FileFilter() {
public boolean accept(File file) {
return file.getName().endsWith(extension);
}
};
// Imagine what would happen when we're allowed to change extension here?
// extension = "foo";
return fileFilter;
}
And here's the exact same example in lambda flavor:
public FileFilter createFileExtensionFilter(final String extension) {
FileFilter fileFilter = file -> file.getName().endsWith(extension);
// Imagine what would happen when we're allowed to change extension here?
// extension = "foo";
return fileFilter;
}
Removing the final modifier would result in compile error, because it isn't guaranteed anymore that the value is a runtime constant. Changing the value after creation of the anonymous class or lambda would namely cause the instance of the anonymous class or lambda to behave different after the moment of creation.
Using final in method parameters - your opinion?
oop - Java `final` method: what does it promise? - Stack Overflow
coding style - In Java, should I use "final" for parameters and locals even when I don't have to? - Software Engineering Stack Exchange
Final, static, and static final in Java
Videos
I would say that this is due to force of habit. The programmer that wrote this code knew as he was writing it that the values for the final variables should never be changed after assignment, and so made them final. Any attempt to assign a new value to a final variable after assignment will result in a compiler error.
As habits go, it's not a bad one to develop. At the least, making a variable final specifies the intent of the programmer at the time of writing. This is important as it might give subsequent programmers who edit the code pause for thought before they start changing how that variable is used.
Speaking as a Java developer who makes all variables final by default (and who appreciates the fact that Eclipse can do this automatically), I find it easier to reason about my program if variables are initialized once and never changed again.
For one thing, uninitialized variables are no longer any concern, because trying to use a final variable before it has been initialized will result in a compile error. This is particularly useful for nested conditional logic, where I want to make sure that I covered all the cases:
final int result;
if (/* something */) {
if (/* something else */) {
result = 1;
}
else if (/* some other thing */) {
result = 2;
}
}
else {
result = 3;
}
System.out.println(result);
Did I cover all the cases? (Hint: No.) Sure enough, this code won't even compile.
One more thing: In general, any time you know that something is always true about a variable, you should try to get your language to enforce it. We do this every day when we specify a variable's type, of course: The language will ensure that values that are not of that type cannot be stored in that variable. Likewise, if you know that a variable should not be reassigned because it already has the value that it should keep for the entire method, then you can get the language to enforce that restriction by declaring it final.
Lastly, there's the matter of habit. Others have mentioned that this is a habit (+1 to Jon for that), but let me say something about why you would want this habit. If you are declaring fields in your class and not local variables in a method, then it's possible for multiple threads to access those fields at the same time. There are some obscure exceptions, but in general, if a field is final, then every thread that uses your class will see the same value for the variable. Conversely, if a field is not final and multiple threads are using your class, you will need to worry about explicit synchronization using synchronized blocks and/or classes from java.util.concurrent. Synchronization is possible, but programming is hard enough already. ;-) So, if you just declare everything final out of habit, then many of your fields will be final and you'll spend as little time as possible worrying about synchronization and concurrency-related bugs.
For more on this habit, check out the "Minimize Mutability" tip in Joshua Bloch's Effective Java.
Edit: @Peter Taylor has pointed out that the example above would also not compile if the final keyword is removed, which is completely correct. When I advised in favor of keeping all local variables final, it's because I wanted to make examples like the following one impossible:
int result = 0;
// OK, time to cover all the cases!
if (/* something */) {
if (/* something else */) {
result = 1;
}
else if (/* some other thing */) {
result = 2;
}
// Whoops, missed an "else" here. Too bad.
}
else {
result = 3;
}
System.out.println(result); // Works fine!
Using a new variable instead of reusing an old one is how I can tell the compiler that trying to cover the complete universe of possibilities, and using final variables forces me to use a new variable instead of recycling an old one.
Another valid complaint about this example is that you should avoid complex nested conditional logic in the first place. That's true, of course, precisely because it's hard to make sure you covered all the cases in the way that you intended. However, sometimes complex logic can't be avoided. When my logic is complex, I want my variables to be as simple to reason about as possible, which I can achieve by making sure my variables' values never change after they are initialized.
Hi there.
In my company people tend to add final to method parameters all over the codebase.
At the same time I believe they don't do it because of any gain it gives them, but just because maybe they were learnt to do so in some course or bootcamp.
I don't see a reason to add final to method arguments in 99% as I tend to program in a way, were you return new object back from the method (so no modification of method parameters) or you design a method in a way that it is obvious that it can change the internals of the passed objects.
Can you convince me that declaring final to method parameters has its upsides and I should change my attitude, or I am the one who is on the right side?
Happy to hear your opinions.
As mentioned, final is used with a Java method to mark that the method can't be overridden (for object scope) or hidden (for static). This allows the original developer to create functionality that cannot be changed by subclasses, and that is all the guarantee it provides.
This means that if the method relies on other customizable components like non-public fields/methods the functionality of the final method may still be customizable. This is good though as (with polymorphism) it allows for partial customization.
There are a number of reasons to prevent something from being customizable, including:
Performance -- Some compilers can analyse and optimise the operation, especially the one without side-effects.
Obtain encapsulated data -- look at immutable Objects where their attributes are set at the construction time and should never be changed. Or a calculated value derived from those attributes. A good example is the Java
Stringclass.Reliability and Contract -- Objects are composed of primitives (
int,char,double, etc.) and/or other Objects. Not all operations applicable to those components should be applicable or even logical when they are used in the bigger Object. Methods with thefinalmodifier can be used to ensure that. The Counter class is a good example.
public class Counter {
private int counter = 0;
public final int count() {
return counter++;
}
public final int reset() {
return (counter = 0);
}
}
If the public final int count() method is not final, we can do something like this:
Counter c = new Counter() {
public int count() {
super.count();
return super.count();
}
}
c.count(); // now count 2
Or something like this:
Counter c = new Counter() {
public int count() {
int lastCount = 0;
for (int i = super.count(); --i >= 0; ) {
lastCount = super.count();
}
return lastCount;
}
}
c.count(); // Now double count
What kind of "contract" does a final method promise?
Look at it the other way, any non final method makes the implicit guarantee that you can override it with your own implementation and the class will still work as expected. When you can't guarantee that your class supports overwriting a method you should make it final.
I use final the same way as you. To me it looks superfluous on local variables and method parameters, and it doesn't convey useful extra information.
One important thing is that strive to keep my methods short and clean, each doing a single task. Thus my local variables and parameters have a very limited scope, and are used only for a single purpose. This minimizes the chances of reassigning them inadvertently.
Moreover, as you surely know, final doesn't guarantee that you can't change the value/state of a (nonprimitive) variable. Only that you can't reassign the reference to that object once initialized. In other words, it works seamlessly only with variables of primitive or immutable types. Consider
final String s = "forever";
final int i = 1;
final Map<String, Integer> m = new HashMap<String, Integer>();
s = "never"; // compilation error!
i++; // compilation error!
m.put(s, i); // fine
This means that in many cases it still doesn't make it easier to understand what happens inside the code, and misunderstanding this may in fact cause subtle bugs which are hard to detect.
Your Java programming style and thoughts are fine - don't need to doubt yourself there.
On the other hand, I find it a lot less useful with locals and parameters, and usually I avoid marking them as final even if they will never be re-assigned into (with the obvious exception when they need to be used in an inner class).
This is exactly why you should use the final keyword. You state that YOU know it'll never be re-assigned, but no one else knows that. Using final immediately disambiguates your code that tiny bit more.
Please correct me if I am wrong, and explain where my understanding is incomplete.
From what I've read both static and final are keywords. If you make a variable or method static, it would only be accessed by the class itself and not by an instance of the class (object). A static class would be useful if it was nested inside another class and you didn't want an instance of the outer class to access the inner class.
If you make a variable final, then it is initialized once and not changed. A final class can't be subclassed, and a final method can't be overwritten. If a variable is static final, then it cannot be changed and it can only be accessed by the class itself and not an object of the class.
People use static all the time, but why is it useful to limit the access of a method or variable to the class itself and not any instances of it?