Update: Original answer below was written without fully understanding the question, and therefore does not directly address the question :)
Nevertheless, it must be informative for those looking to understand the general use of final
keyword.
As for the question, I would like to quote my own comment from below.
I believe you're not forced to implement the finality of an argument to leave you free to decide whether it should be final or not in your own implementation.
But yes, it sounds rather odd that you can declare it final
in the interface, but have it non-final in the implementation. It would have made more sense if either:
a. final
keyword was not allowed for interface (abstract) method arguments (but you can use it in implementation), or
b. declaring an argument as final
in interface would force it to be declared final
in implementation (but not forced for non-finals).
I can think of two reasons why a method signature can have final
parameters: Beans and Objects (Actually, they are both the same reason, but slightly different contexts.)
Objects:
public static void main(String[] args) {
StringBuilder cookingPot = new StringBuilder("Water ");
addVegetables(cookingPot);
addChicken(cookingPot);
System.out.println(cookingPot.toString());
// ^--- OUTPUT IS: Water Carrot Broccoli Chicken ChickenBroth
// We forgot to add cauliflower. It went into the wrong pot.
}
private static void addVegetables(StringBuilder cookingPot) {
cookingPot.append("Carrot ");
cookingPot.append("Broccoli ");
cookingPot = new StringBuilder(cookingPot.toString());
// ^--- Assignment allowed...
cookingPot.append("Cauliflower ");
}
private static void addChicken(final StringBuilder cookingPot) {
cookingPot.append("Chicken ");
//cookingPot = new StringBuilder(cookingPot.toString());
// ^---- COMPILATION ERROR! It is final.
cookingPot.append("ChickenBroth ");
}
The final
keyword ensured that we will not accidentally create a new local cooking pot by showing a compilation error when we attempted to do so. This ensured the chicken broth is added to our original cooking pot which the addChicken
method got. Compare this to addVegetables
where we lost the cauliflower because it added that to a new local cooking pot instead of the original pot it got.
Beans:
It is the same concept as objects (as shown above). Beans are essentially Object
s in Java. However, beans (JavaBeans) are used in various applications as a convenient way to store and pass around a defined collection of related data. Just as the addVegetables
could mess up the cooking process by creating a new cooking pot StringBuilder
and throwing it away with the cauliflower, it could also do the same with a cooking pot JavaBean.
final
doesn't do anything with native types anyway, since they're copied. – Duesterinterface
definitions vary only in thefinal
attribute of an argument, then the resulting.class
files are byte-for-byte identically (and of coursejavap -v
produces the same output). The same is true for two classes that only differ infinal
on an attribute, by the way! – Unbeknown