Popular Searches
Popular Course Categories
Popular Courses

Using the final Keyword with Variables, Methods, and Classes

Using the final Keyword with Variables, Methods, and Classes

Access Modifiers, Static Members, and Final Keyword

Using the final Keyword with Variables, Methods, and Classes in Java

Course: Core Java Training

Topic: Using the final Keyword with Variables, Methods, and Classes

Course Link: Core Java Training Course

Demo Link: Register for a Course Demo

Website: JustAcademy Official Website


1. Introduction to the final Keyword in Java

The final keyword in Java is a non-access modifier used to restrict changes to variables, methods, and classes. It helps developers create constants, prevent method overriding, and prevent class inheritance where necessary.

The meaning of final depends on where it is used. When applied to a variable, it prevents reassignment after initialization. When applied to a method, it prevents subclasses from overriding that method. When applied to a class, it prevents other classes from extending it.

Using final appropriately can improve code safety, readability, and maintainability by making important restrictions explicit.

Learning Objectives

  • Understand the purpose and meaning of the final keyword.
  • Learn how to use final variables and constants.
  • Understand final instance variables, static variables, and local variables.
  • Learn how final methods prevent overriding.
  • Understand how final classes prevent inheritance.
  • Differentiate final variables from immutable objects.
  • Explore blank final variables and constructor initialization.
  • Identify common errors and apply best practices.

2. What Is the final Keyword?

The final keyword restricts certain changes to a Java program. It can be used with variables, methods, and classes. Each use serves a different purpose.

Basic Syntax

final dataType variableName = value;

final returnType methodName() {
    // Method implementation
}

final class ClassName {
    // Class implementation
}

Example

final int MAX_ATTEMPTS = 3;

System.out.println(MAX_ATTEMPTS);

Output

3

In this example, MAX_ATTEMPTS is a final variable. After it has been initialized, it cannot be assigned a different value.

3. Using final with Variables

When the final keyword is applied to a variable, the variable can be assigned only once. Once initialized, it cannot be reassigned.

A final variable must be initialized before it is used. Depending on its declaration, initialization can happen at the declaration, in an initialization block, or in a constructor.

Syntax

final int number = 100;

Example: Final Variable

class FinalVariableExample {
    public static void main(String[] args) {
        final int age = 25;

        System.out.println("Age: " + age);

        // age = 30; // Compilation error
    }
}

Output

Age: 25

The statement age = 30; would cause a compilation error because the final variable has already been initialized.

Important Points

  • A final variable cannot be reassigned after initialization.
  • A final local variable must be definitely assigned before it is read.
  • A final field must be initialized according to Java's field initialization rules.
  • Final variables are useful for values that should remain fixed after assignment.
  • The meaning of final depends on whether the variable stores a primitive value or an object reference.

4. Using final with Primitive Variables

A primitive variable stores a value such as an integer, character, boolean, or floating-point number. When a primitive variable is declared final, its value cannot be reassigned after initialization.

Example

class PrimitiveFinalExample {
    public static void main(String[] args) {
        final int number = 50;
        final double price = 199.99;
        final char grade = 'A';
        final boolean active = true;

        System.out.println(number);
        System.out.println(price);
        System.out.println(grade);
        System.out.println(active);
    }
}

Output

50
199.99
A
true

All four variables are final. Assigning another value to any of them after initialization would cause a compilation error.

5. Using final with Reference Variables

A reference variable stores a reference to an object rather than the object itself. When a reference variable is declared final, the reference cannot be reassigned to another object after initialization.

However, if the referenced object is mutable, its internal state may still be changed. Therefore, a final reference does not automatically make the object immutable.

Example

class Student {
    String name;

    Student(String name) {
        this.name = name;
    }
}

class FinalReferenceExample {
    public static void main(String[] args) {
        final Student student = new Student("Rahul");

        student.name = "Amit";

        System.out.println(student.name);

        // student = new Student("Priya");
        // Compilation error
    }
}

Output

Amit

The student's name can change because the object is mutable. The reference variable student cannot be made to refer to a different object after initialization.

Key Difference

  • Final reference: Prevents reassignment of the reference.
  • Mutable object: Its internal state may still change.
  • Immutable object: Its state cannot be changed after construction through its public interface.

6. Using final with Instance Variables

An instance variable belongs to an object. When declared final, it must be initialized exactly once for each object. It can be initialized directly where it is declared or assigned through an instance initialization block or constructor.

Example: Final Instance Variable

class Employee {
    final int employeeId;
    String employeeName;

    Employee(int employeeId, String employeeName) {
        this.employeeId = employeeId;
        this.employeeName = employeeName;
    }

    void display() {
        System.out.println("Employee ID: " + employeeId);
        System.out.println("Employee Name: " + employeeName);
    }

    public static void main(String[] args) {
        Employee e1 = new Employee(101, "Aman");
        Employee e2 = new Employee(102, "Priya");

        e1.display();
        e2.display();
    }
}

Output

Employee ID: 101
Employee Name: Aman
Employee ID: 102
Employee Name: Priya

Each employee object receives its own final employee ID. The ID cannot be reassigned after construction, while the employee name can be changed because it is not final.

7. Using final with Static Variables

A static variable belongs to the class rather than to individual objects. Combining static and final is a common way to declare constants that are shared by the class.

Syntax

static final dataType CONSTANT_NAME = value;

Example: Application Constants

class AppConstants {
    static final double PI = 3.14159;
    static final int MAX_USERS = 100;
    static final String APPLICATION_NAME = "Student Portal";

    public static void main(String[] args) {
        System.out.println(PI);
        System.out.println(MAX_USERS);
        System.out.println(APPLICATION_NAME);
    }
}

Output

3.14159
100
Student Portal

These values are shared class-level fields and cannot be reassigned after initialization.

Best Practices for Constants

  • Use static final for suitable class-level constants.
  • Use descriptive names that clearly communicate the constant's purpose.
  • For conventional Java constant naming, use uppercase letters and underscores, such as MAX_RETRIES.
  • Prefer constants over repeated literal values when the value has a clear shared meaning.
  • Remember that a final reference to a mutable object does not make the referenced object immutable.

8. Using final with Local Variables

A local variable is declared inside a method, constructor, or block. When a local variable is declared final, it can be assigned only once.

Example

class LocalFinalExample {
    public static void main(String[] args) {
        final int marks;

        marks = 85;

        System.out.println("Marks: " + marks);

        // marks = 90; // Compilation error
    }
}

Output

Marks: 85

This example demonstrates a blank final local variable. It is declared without an initial value and assigned later. The assignment must occur before the variable is read, and it cannot be assigned again.

Final Variables in Loops

A final local variable cannot be reassigned during repeated loop iterations. If a value must change on each iteration, use a non-final variable or declare a separate final variable for each appropriate scope.

9. Understanding Blank final Variables

A blank final variable is declared without an initializer. It must be assigned exactly once before it is used. This approach is useful when the value is available only when an object is created.

Example: Blank final Instance Variable

class Product {
    final int productId;

    Product(int productId) {
        this.productId = productId;
    }

    void display() {
        System.out.println("Product ID: " + productId);
    }

    public static void main(String[] args) {
        Product p1 = new Product(501);
        Product p2 = new Product(502);

        p1.display();
        p2.display();
    }
}

Output

Product ID: 501
Product ID: 502

The constructor initializes the blank final instance field for each object. Every object receives its own product ID, and that ID cannot be reassigned afterward.

Blank final static Variables

A blank final static variable can be initialized in a static initialization block.

class DatabaseConfig {
    static final String DATABASE_NAME;

    static {
        DATABASE_NAME = "StudentDB";
    }

    public static void main(String[] args) {
        System.out.println(DATABASE_NAME);
    }
}

Output

StudentDB

A blank final static field must be definitely assigned during class initialization, typically through its declaration or a static initialization block.

10. Using final with Method Parameters

The final keyword can also be applied to method parameters. This prevents the parameter variable from being reassigned within the method body.

Example

class MethodParameterExample {
    static void display(final int number) {
        System.out.println("Number: " + number);

        // number = 100; // Compilation error
    }

    public static void main(String[] args) {
        display(25);
    }
}

Output

Number: 25

Here, the parameter number cannot be assigned another value inside the method. For reference-type parameters, final prevents reassignment of the reference, but does not necessarily prevent changes to the referenced object.

11. Using final with Methods

When a method is declared final, a subclass cannot override that method. This is useful when a class needs to preserve specific behavior that subclasses must not replace.

Syntax

class Parent {
    final void display() {
        System.out.println("This method cannot be overridden");
    }
}

Example: Final Method

class Bank {
    final void showBankPolicy() {
        System.out.println("Standard bank policy");
    }
}

class SavingsAccount extends Bank {
    void displayAccountType() {
        System.out.println("Savings Account");
    }
}

class FinalMethodExample {
    public static void main(String[] args) {
        SavingsAccount account = new SavingsAccount();

        account.showBankPolicy();
        account.displayAccountType();
    }
}

Output

Standard bank policy
Savings Account

The subclass inherits the final method and can use it, but it cannot provide an overriding implementation of that method.

Attempting to Override a Final Method

class Parent {
    final void show() {
        System.out.println("Parent method");
    }
}

class Child extends Parent {
    // Compilation error: cannot override final method
    // void show() {
    //     System.out.println("Child method");
    // }
}

If the subclass declares an instance method that attempts to override an inherited final instance method, the compiler reports an error.

12. Important Rules for Final Methods

  • A final instance method cannot be overridden by a subclass.
  • A final method can be inherited and called by a subclass if access rules permit.
  • A final method can be overloaded with a different parameter list.
  • Constructors cannot be declared final because constructors are not inherited or overridden.
  • Private methods cannot be overridden because they are not inherited in the normal overriding sense; declaring a private method final is generally redundant.
  • A static method cannot be overridden through instance-method polymorphism. A compatible static method declared in a subclass is considered method hiding, not overriding.

Example: Overloading a Final Method

class Message {
    final void display() {
        System.out.println("Default message");
    }

    final void display(String text) {
        System.out.println(text);
    }

    public static void main(String[] args) {
        Message message = new Message();

        message.display();
        message.display("Welcome to Java");
    }
}

Output

Default message
Welcome to Java

Both methods are final, but they have different parameter lists. Method overloading is allowed because neither method overrides the other.

13. Using final with Classes

When a class is declared final, another class cannot extend it. This prevents inheritance from that class and can help protect its design or behavior from being changed through subclassing.

Syntax

final class ClassName {
    // Class members
}

Example: Final Class

final class SecurityConfig {
    void display() {
        System.out.println("Security configuration");
    }
}

class FinalClassExample {
    public static void main(String[] args) {
        SecurityConfig config = new SecurityConfig();
        config.display();
    }
}

Output

Security configuration

The class can be instantiated and its accessible methods can be called. However, another class cannot extend SecurityConfig.

Attempting to Extend a Final Class

final class Vehicle {
    void start() {
        System.out.println("Vehicle started");
    }
}

// Compilation error: cannot inherit from final Vehicle
// class Car extends Vehicle {
// }

Java rejects the inheritance declaration because Vehicle is final.

14. Characteristics of Final Classes

  • A final class cannot be extended by another class.
  • A final class can contain constructors, variables, static methods, and instance methods.
  • A final class can implement interfaces.
  • A final class can extend a non-final superclass.
  • Declaring a class final does not automatically make all its fields final.
  • A final class is not automatically immutable; its objects can still be mutable.

Example: Final Class Implementing an Interface

interface Printable {
    void print();
}

final class Report implements Printable {
    public void print() {
        System.out.println("Printing report");
    }
}

class FinalInterfaceExample {
    public static void main(String[] args) {
        Printable report = new Report();
        report.print();
    }
}

Output

Printing report

The class Report is final, but it can still implement an interface and provide its required method implementation.

15. Difference Between final Variables, Methods, and Classes

Feature final Variable final Method final Class
Purpose Prevents reassignment Prevents overriding of an instance method Prevents inheritance
Used with Variables and parameters Methods Class declarations
Inheritance effect Does not prevent inheritance Method is inherited but cannot be overridden Class cannot be extended
Object creation Depends on the declaring type Objects can be created normally Objects can be created normally
Common example final int age = 20; final void display() final class Utility

16. Difference Between final, finally, and finalize()

These three terms look similar, but they serve different purposes in Java.

Term Type Purpose
final Keyword Restricts reassignment, method overriding, or class inheritance.
finally Block used with exception handling Normally executes after a try/catch sequence to perform cleanup, subject to abnormal termination and other execution conditions.
finalize() Legacy method of Object Historically associated with cleanup before garbage collection; deprecated and should not be relied upon.

Example of final

final int value = 10;

Example of finally

try {
    System.out.println("Inside try block");
} finally {
    System.out.println("Cleanup block");
}

Output

Inside try block
Cleanup block

Use final for restrictions, finally for appropriate cleanup logic, and modern resource-management approaches such as try-with-resources when working with resources that implement AutoCloseable. Avoid relying on finalize().

17. final and Immutability

Immutability means that an object's state cannot be changed after the object has been constructed. The final keyword can support immutable class design, but using final alone does not guarantee immutability.

Example: A Mutable Object with a Final Reference

class Box {
    int value;
}

class FinalObjectExample {
    public static void main(String[] args) {
        final Box box = new Box();

        box.value = 100;

        System.out.println(box.value);
    }
}

Output

100

The reference box cannot be reassigned, but the value inside the referenced object can change.

Characteristics of an Immutable Class

  • Declare the class final when preventing subclass-based changes is appropriate.
  • Make fields private and final where suitable.
  • Initialize fields during object construction.
  • Do not provide methods that modify the object's state.
  • Use defensive copies for mutable objects passed into or returned from the class.

Example: Immutable Class

final class Person {
    private final String name;
    private final int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

class ImmutableExample {
    public static void main(String[] args) {
        Person person = new Person("Aman", 25);

        System.out.println(person.getName());
        System.out.println(person.getAge());
    }
}

Output

Aman
25

The class is final, its fields are private and final, and it exposes no methods that change its state. Because the fields contain immutable types, this is a simple example of an immutable class.

18. Advantages of Using the final Keyword

  • Prevents accidental reassignment: Final variables protect values that must remain fixed.
  • Supports constants: Static final fields are useful for shared constant values.
  • Protects method behavior: Final instance methods prevent subclasses from overriding important implementations.
  • Restricts inheritance: Final classes prevent subclasses from changing or extending their behavior.
  • Improves readability: Other developers can understand which values or behaviors are intended to remain fixed.
  • Supports safer design: Final fields help implement objects whose state is established during construction.
  • Helps maintainability: Explicit restrictions can reduce unintended changes during future development.

19. Limitations of the final Keyword

  • A final variable cannot be reassigned, which may be unsuitable for values that must change.
  • A final method limits customization through overriding.
  • A final class prevents inheritance and may reduce extensibility.
  • A final reference does not automatically make a mutable object immutable.
  • Final fields do not automatically make every operation on an object thread-safe.
  • Excessive use of final can make a design unnecessarily restrictive if future extension is a requirement.

20. Common Errors and How to Fix Them

Error Reason Solution
Reassigning a final variable The variable has already been initialized. Initialize it correctly once or remove final if reassignment is required.
Using an uninitialized blank final field The field has not been definitely assigned. Initialize it in the declaration, an appropriate initialization block, or every relevant constructor path.
Overriding a final method Java prohibits overriding a final instance method. Use the inherited method or redesign the superclass if customization is needed.
Extending a final class Final classes cannot have subclasses. Use composition or extend a non-final class instead.
Assuming a final object cannot change Final restricts the reference, not necessarily the object's state. Use an immutable object design where required.
Declaring a final field without initialization A final field must be definitely assigned. Initialize it through a valid field initializer, initialization block, or constructor.

21. Best Practices for Using final

  • Use final for values that should not be reassigned.
  • Use static final for suitable shared constants.
  • Initialize final instance fields through constructors when their values depend on object creation parameters.
  • Use final methods only when preventing subclass overriding is an intentional design decision.
  • Declare classes final when subclassing should not be permitted.
  • Do not confuse a final reference with an immutable object.
  • Use private fields and controlled access to protect object state.
  • Choose immutability deliberately when building value objects or thread-safe components.
  • Avoid restricting inheritance or overriding without a clear requirement.

22. Practice Exercises

Exercise 1: Final Variable

Declare a final integer variable called MAX_MARKS, initialize it to 100, and display its value. Then uncomment an assignment that changes its value and observe the compiler error.

Exercise 2: Final Instance Variable

Create a Student class with a final roll number and a mutable name. Initialize both values through a constructor and display them.

Exercise 3: Final Method

Create a parent class containing a final method. Create a child class that inherits from the parent and call the inherited method. Then try overriding the method to understand the compilation error.

Exercise 4: Final Class

Create a final class named BankPolicy with a method that displays a message. Instantiate the class and call its method. Then attempt to extend the class.

Exercise 5: Immutable Class

Create an immutable Book class with private final fields for the title and author. Initialize both fields in the constructor and provide getter methods without setters.

23. Mini Project: Employee Record with final Fields

Objective: Build a simple employee record program that demonstrates final instance variables and static final constants.

Requirements

  • Create an EmployeeRecord class.
  • Declare employee ID and employee name as private final instance fields.
  • Declare a static final constant for the company name.
  • Initialize the employee details using a constructor.
  • Provide getter methods to access the details.
  • Display information for multiple employee objects.

Sample Implementation

class EmployeeRecord {
    private final int employeeId;
    private final String employeeName;

    static final String COMPANY_NAME = "JustAcademy";

    EmployeeRecord(int employeeId, String employeeName) {
        this.employeeId = employeeId;
        this.employeeName = employeeName;
    }

    public int getEmployeeId() {
        return employeeId;
    }

    public String getEmployeeName() {
        return employeeName;
    }

    void displayDetails() {
        System.out.println("Employee ID: " + employeeId);
        System.out.println("Employee Name: " + employeeName);
        System.out.println("Company: " + COMPANY_NAME);
    }

    public static void main(String[] args) {
        EmployeeRecord e1 = new EmployeeRecord(101, "Aman");
        EmployeeRecord e2 = new EmployeeRecord(102, "Priya");

        e1.displayDetails();
        e2.displayDetails();
    }
}

Expected Output

Employee ID: 101
Employee Name: Aman
Company: JustAcademy
Employee ID: 102
Employee Name: Priya
Company: JustAcademy

This project demonstrates how final instance fields protect employee-specific values from reassignment, while a static final field stores a shared constant.

24. Java Interview Questions and Answers

Q1. What is the final keyword in Java?

The final keyword restricts reassignment of variables, overriding of instance methods, and inheritance from classes.

Q2. Can a final variable be changed?

A final variable cannot be reassigned after initialization. If it holds a reference to a mutable object, the object's internal state may still change.

Q3. What is a blank final variable?

A blank final variable is declared without an initializer and must be assigned exactly once before it is used.

Q4. Can a final variable be initialized in a constructor?

Yes. A blank final instance field can be initialized in a constructor, provided it is definitely assigned on every valid constructor path.

Q5. What happens when a method is declared final?

A final instance method cannot be overridden by a subclass, although it can be inherited and called.

Q6. Can a final method be overloaded?

Yes. Overloading is allowed when methods have different parameter lists.

Q7. Can a final class be inherited?

No. A final class cannot be extended by another class.

Q8. Can a final class implement an interface?

Yes. A final class can implement one or more interfaces.

Q9. What is the difference between final and static final?

final prevents reassignment of a variable. static final declares a class-level field that is shared and cannot be reassigned after initialization.

Q10. Does final make an object immutable?

No. A final reference cannot be reassigned, but the referenced object may remain mutable. Immutability requires additional design decisions.

Q11. Can a constructor be final?

No. Constructors cannot be declared final because they are not inherited or overridden.

Q12. What is the difference between final, finally, and finalize()?

final restricts variables, methods, and classes; finally is an exception-handling block; and finalize() is a deprecated legacy cleanup mechanism that should not be relied upon.

Q13. Can an abstract class be final?

No. An abstract class is intended to be extended, while a final class cannot be extended. These modifiers conflict when applied to the same class.

Q14. Can an interface be declared final?

No. Interfaces are implemented by classes rather than extended as concrete classes, and Java does not permit an interface declaration to be final.

Q15. Why are final fields useful?

Final fields help ensure that important values are assigned once and remain stable after initialization, supporting safer and more predictable object design.

25. Quick Revision Checklist

  • final is a Java keyword used to restrict changes.
  • A final variable cannot be reassigned after initialization.
  • A final reference does not necessarily make its object immutable.
  • A final instance field can be initialized in a constructor.
  • A blank final static field can be initialized in a static initialization block.
  • A final method cannot be overridden by a subclass.
  • A final method can still be overloaded.
  • A final class cannot be extended.
  • A final class can implement interfaces.
  • Constructors cannot be declared final.
  • static final is commonly used for class-level constants.
  • final, finally, and finalize() have different meanings.
  • Use final intentionally to improve code clarity and protect important behavior.

26. Conclusion

The final keyword is an important part of Java programming. It helps developers control how variables, methods, and classes can be changed or extended. Final variables prevent reassignment, final instance methods prevent overriding, and final classes prevent inheritance.

Understanding the distinction between final references and immutable objects is especially important when working with object-oriented applications. By using final fields, constants, methods, and classes appropriately, developers can build Java programs that are more predictable, maintainable, and easier to understand.

Learn More with JustAcademy

Continue learning Java programming through the Core Java Training Course. Explore object-oriented programming, classes, constructors, inheritance, polymorphism, exception handling, collections, and other essential Java concepts.

To explore course options, register for a course demo or visit the JustAcademy official website.

Previous Next
whatsapp