Final
In Java, the final
keyword is used to define constants, prevent inheritance, and restrict method overriding. When it comes to variables, final
ensures that the variable can only be assigned once.
Final Variables
variable declared with final
is a constant, meaning its value cannot be changed once assigned.
- Final Instance Variables: These are initialized when the instance is created. It must be initialized either at the point of declaration or within every constructor. If not initialized in all constructors, it will cause a compilation error.
- Final Static Variables: These are initialized once when the class is loaded. It must be initialized at the point of declaration or within a static block. Once set, their value cannot change.
- Final Local Variables: These are used inside methods or blocks and must be initialized before use.
public class FinalVariableExample {
// Final instance variable
final int instanceVar;
// Final static variable
static final int STATIC_VAR = 100;
// Constructor to initialize the final instance variable
public FinalVariableExample(int value) {
this.instanceVar = value;
}
public void demonstrateFinalLocalVariable() {
// Final local variable
final int localVar;
localVar = 50;
// Uncommenting the following line will cause a compilation error
// localVar = 60;
System.out.println("Local final variable: " + localVar);
}
public static void main(String[] args) {
FinalVariableExample example = new FinalVariableExample(10);
System.out.println("Instance final variable: " + example.instanceVar);
System.out.println("Static final variable: " + STATIC_VAR);
example.demonstrateFinalLocalVariable();
}
}
Final Methods
Method declared with final
cannot be overridden by subclasses. This is useful to prevent altering the intended behavior of a method in subclasses.
class ParentClass {
// Final method
public final void display() {
System.out.println("This is a final method in the parent class.");
}
}
class ChildClass extends ParentClass {
// Uncommenting the following method will cause a compilation error
// public void display() {
// System.out.println("This would cause an error.");
// }
}
public class FinalMethodExample {
public static void main(String[] args) {
ChildClass child = new ChildClass();
child.display();
}
}
Final Classes
// Final class
final class FinalClass {
public void show() {
System.out.println("This is a method in a final class.");
}
}
// Uncommenting the following class will cause a compilation error
// class SubClass extends FinalClass {
// }
public class FinalClassExample {
public static void main(String[] args) {
FinalClass finalClassInstance = new FinalClass();
finalClassInstance.show();
}
}
Effectively Final
An effectively final variable
is one that is not declared with the final
keyword but is never modified after its initial assignment. It applies to local variables and method parameters that are not explicitly declared as final
but are never modified after their initial assignment. The concept of effectively final is particularly important when working with lambda expressions, anonymous classes, and inner classes.
Objects or primitive values are effectively final if we do not change their values after initialization. In the case of objects, if we do not change the reference of an object, then it is effectively final — even if a change occurs in the state of the referenced object.
public class EffectivelyFinalExample {
public static void main(String[] args) {
int num = 10; // num is effectively final because it is not modified after initialization
// Lambda expression capturing the effectively final variable num
Runnable runnable = () -> System.out.println("Value of num is: " + num);
// Execute the lambda expression
runnable.run();
}
}
public class MethodParameterExample {
public static void main(String[] args) {
printValue(5);
}
public static void printValue(int value) {
// value is effectively final because it is not modified within the method
// Anonymous class capturing the effectively final parameter value
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Value is: " + value);
}
};
// Execute the anonymous class's run method
runnable.run();
}
}