In Java we use final
keyword with variables to specify its values are not to be changed.
But I see that you can change the value in the constructor / methods of
Final keyword has a numerous way to use:
Other usage:
A static class variable will exist from the start of the JVM, and should be initialized in the class. The error message won't appear if you do this.
final
just binds the reference to particular object. You are free to change the 'state' of that object, but not the object itself.I thought of writing an updated and in depth answer here.
final
keyword can be used in several places.
A final class
means that no other class can extend that final class. When Java Run Time (JRE) knows an object reference is in type of a final class (say F), it knows that the value of that reference can only be in type of F.
Ex:
F myF;
myF = new F(); //ok
myF = someOther; //someOther cannot be in type of a child class of F.
//because F cannot be extended.
So when it executes any method of that object, that method doesn't need to be resolved at run time using a virtual table. i.e. run-time polymorphism cannot be applied. So the run time doesn't bother about that. Which means it saves processing time, which will improve performance.
A final method
of any class means that any child class extending that class cannot override that final method(s). So the run time behavior in this scenario is also quite same with the previous behavior I mentioned for classes.
If one specified any kind of above as final
, it means that the value is already finalized, so the value cannot be changed.
Ex:
For fields, local parameters
final FinalClass fc = someFC; //need to assign straight away. otherwise compile error.
final FinalClass fc; //compile error, need assignment (initialization inside a constructor Ok, constructor can be called only once)
final FinalClass fc = new FinalClass(); //ok
fc = someOtherFC; //compile error
fc.someMethod(); //no problem
someOtherFC.someMethod(); //no problem
For method parameters
void someMethod(final String s){
s = someOtherString; //compile error
}
This simply means that value of the final
reference value cannot be changed. i.e. only one initialization is allowed. In this scenario, in run time, since JRE knows that values cannot be changed, it loads all these finalized values (of final references) into L1 cache. Because it doesn't need to load back again and again from main memory. Otherwise it loads to L2 cache and does time to time loading from main memory. So it is also a performance improvement.
So in all above 3 scenarios, when we have not specified the final
keyword in places we can use, we don't need to worry, compiler optimizations will do that for us. There are also lots of other things that compiler optimizations do for us. :)
You are always allowed to initialize a final
variable. The compiler makes sure that you can do it only once.
Note that calling methods on an object stored in a final
variable has nothing to do with the semantics of final
. In other words: final
is only about the reference itself, and not about the contents of the referenced object.
Java has no concept of object immutability; this is achieved by carefully designing the object, and is a far-from-trivial endeavor.
final
is a reserved keyword in Java to restrict the user and it can be applied to member variables, methods, class and local variables. Final variables are often declared with the static
keyword in Java and are treated as constants. For example:
public static final String hello = "Hello";
When we use the final
keyword with a variable declaration, the value stored inside that variable cannot be changed latter.
For example:
public class ClassDemo {
private final int var1 = 3;
public ClassDemo() {
...
}
}
Note: A class declared as final cannot be extended or inherited (i.e, there cannot be a subclass of the super class). It is also good to note that methods declared as final cannot be overridden by subclasses.
Benefits of using the final keyword are addressed in this thread.
First of all, the place in your code where you are initializing (i.e. assigning for the first time) foo is here:
foo = new ArrayList();
foo is an object (with type List) so it is a reference type, not a value type (like int). As such, it holds a reference to a memory location (e.g. 0xA7D2A834) where your List elements are stored. Lines like this
foo.add("foo"); // Modification-1
do not change the value of foo (which, again, is just a reference to a memory location). Instead, they just add elements into that referenced memory location. To violate the final keyword, you would have to try to re-assign foo as follows again:
foo = new ArrayList();
That would give you a compilation error.
Now, with that out of the way, think about what happens when you add the static keyword.
When you do NOT have the static keyword, each object that instantiates the class has its own copy of foo. Therefore, the constructor assigns a value to a blank, fresh copy of the foo variable, which is perfectly fine.
However, when you DO have the static keyword, only one foo exists in memory that is associated with the class. If you were to create two or more objects, the constructor would be attempting to re-assign that one foo each time, violating the final keyword.