Final Fields

Introduction

The final keyword makes a field constant - its value cannot be changed after initialization.


Syntax

final dataType fieldName = value;

Basic Example

class Circle {
    final double PI = 3.14159;  // Final field
    double radius;

    double getArea() {
        return PI * radius * radius;
    }

    void changePI() {
        // PI = 3.14;  // ❌ Error: cannot change final field
    }
}

public class Main {
    public static void main(String[] args) {
        Circle c = new Circle();
        c.radius = 5;
        System.out.println("Area: " + c.getArea());

        // c.PI = 3.14;  // ❌ Error: cannot change final field
    }
}

Initialization of Final Fields

1. At Declaration:

class Constants {
    final int MAX_SIZE = 100;
    final String APP_NAME = "MyApp";
    final double TAX_RATE = 0.18;
}

2. In Constructor:

class Student {
    final int rollNo;  // Not initialized here
    String name;

    Student(int rollNo, String name) {
        this.rollNo = rollNo;  // Initialize in constructor
        this.name = name;
    }

    void display() {
        System.out.println("Roll No: " + rollNo);
        System.out.println("Name: " + name);
    }
}

public class Main {
    public static void main(String[] args) {
        Student s = new Student(101, "John");
        s.display();

        s.name = "Alice";  // ✓ OK: name is not final
        // s.rollNo = 102;  // ❌ Error: rollNo is final
    }
}

3. In Initialization Block:

class Example {
    final int value;

    // Initialization block
    {
        value = 100;
    }
}

Final Fields Must Be Initialized

class Wrong {
    final int x;  // ❌ Error: final field not initialized
}

class Correct1 {
    final int x = 10;  // ✓ OK: initialized at declaration
}

class Correct2 {
    final int x;

    Correct2() {
        x = 10;  // ✓ OK: initialized in constructor
    }
}

Constants with Final

class MathConstants {
    final double PI = 3.14159;
    final double E = 2.71828;
    final int MAX_VALUE = Integer.MAX_VALUE;
}

class Config {
    final String DATABASE_URL = "localhost:3306";
    final int MAX_CONNECTIONS = 100;
    final int TIMEOUT = 30;
}

Final with Static

Static final = Class-level constant (most common for constants).

class Circle {
    static final double PI = 3.14159;  // Class constant
    double radius;

    double getArea() {
        return PI * radius * radius;
    }
}

public class Main {
    public static void main(String[] args) {
        // Access without creating object
        System.out.println("PI = " + Circle.PI);

        Circle c1 = new Circle();
        Circle c2 = new Circle();
        // Both share same PI value
    }
}

Complete Example

class BankAccount {
    final String accountNumber;  // Final field
    final String accountType;    // Final field
    private double balance;      // Can change

    // Initialize final fields in constructor
    BankAccount(String accountNumber, String accountType) {
        this.accountNumber = accountNumber;
        this.accountType = accountType;
        this.balance = 0.0;
    }

    void deposit(double amount) {
        balance += amount;
    }

    void display() {
        System.out.println("Account: " + accountNumber);
        System.out.println("Type: " + accountType);
        System.out.println("Balance: " + balance);
    }
}

public class Main {
    public static void main(String[] args) {
        BankAccount acc = new BankAccount("1234567890", "Savings");
        acc.deposit(1000);
        acc.display();

        // acc.accountNumber = "9999";  // ❌ Error: final field
        // acc.accountType = "Current";  // ❌ Error: final field
        acc.deposit(500);  // ✓ OK: balance can change
    }
}

Naming Convention

Constants (static final fields) are typically named in UPPER_CASE.

class Constants {
    static final int MAX_SIZE = 100;
    static final String APP_NAME = "MyApp";
    static final double PI = 3.14159;
    static final int MIN_AGE = 18;
}

Final vs Non-Final

class Example {
    final int CONSTANT = 100;     // Cannot change
    int variable = 200;           // Can change

    void test() {
        // CONSTANT = 150;  // ❌ Error
        variable = 250;     // ✓ OK
    }
}

Practical Use Cases

1. Configuration Values:

class AppConfig {
    static final String VERSION = "1.0.0";
    static final int MAX_USERS = 1000;
    static final String API_URL = "https://api.example.com";
}

2. Unique Identifiers:

class Employee {
    final int empId;  // Cannot change once assigned
    String name;      // Can be updated

    Employee(int empId, String name) {
        this.empId = empId;
        this.name = name;
    }
}

3. Mathematical Constants:

class Physics {
    static final double SPEED_OF_LIGHT = 299792458;  // m/s
    static final double GRAVITY = 9.8;               // m/s²
}

Benefits of Final Fields

  1. Immutability: Values cannot be changed
  2. Thread Safety: Safe to share across threads
  3. Compiler Optimization: Better performance
  4. Intent: Shows value should not change
  5. Error Prevention: Prevents accidental modification

Comparison Table

TypeKeywordScopeCan Change?
Instance constantfinalPer objectNo
Class constantstatic finalPer classNo
Instance variable(none)Per objectYes
Class variablestaticPer classYes

Quick Reference

class Example {
    // Class constant (most common)
    static final int MAX = 100;

    // Instance constant
    final String id;

    // Regular field
    int count;

    Example(String id) {
        this.id = id;  // Initialize final field
    }
}

// Usage
System.out.println(Example.MAX);  // Access class constant

Example obj = new Example("A001");
// obj.id = "B002";  // ❌ Error: final
obj.count = 10;      // ✓ OK: not final

Exam Tips

Remember:

  1. final fields = constant, cannot change
  2. Must initialize once
  3. Initialize at: declaration, constructor, or initialization block
  4. static final = class constant (common pattern)
  5. Constants named in UPPER_CASE
  6. Provides immutability
  7. Cannot reassign after initialization
  8. Good for IDs, config values, constants

Common Questions:

  • What is final keyword?
  • Can final fields be changed?
  • Where to initialize final fields?
  • Difference between final and non-final?
  • What is static final?
  • Naming convention for constants?
  • Benefits of final fields?