Course Content
Core Java
About Lesson

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();
    }
}

Scroll to Top