Final Variable

In Java, the final keyword can be applied to instance, static, and local variables — but each behaves a little differently once you add it. This post walks through what changes for each of the three, with the compile-time errors you'll actually see if you get it wrong.

Final Instance Variable

  • If the value of a variable changes from object to object, such a variable is called an instance variable.
  • For every object, a separate copy of the instance variable will be created.
  • Instance variables do not require explicit initialization; JVM always provides default values.
Example:
class Test {
    int x;        // instance variable

    public static void main(String... args) {
        Test t = new Test();
        System.out.println(t.x);   // output: 0
    }
}
  • If the instance variable is declared as final, then explicit initialization is mandatory. JVM will NOT provide default values.
Example:
class Test {
    final int x;
}

Compile-time Error: variable x might not have been initialized.

Rule: A final instance variable must be initialized before constructor completion.

Possible places for initialization

1. At the time of declaration
class Test {
    final int x = 10;
}
2. Inside an instance block
class Test {
    final int x;

    {
        x = 10;
    }
}
3. Inside the constructor
class Test {
    final int x;

    Test() {
        x = 10;
    }
}

These are the only valid places for initialization. Assigning anywhere else results in an error.

Invalid Example:
class Test {
    final int x;

    public static void m() {
        x = 10;   // Invalid
    }
}

Compile-time Error: cannot assign a value to final variable x.

Final Static Variables

If a variable's value does not vary from object to object, it should be declared at the class level using the static modifier.

Static variables have a single copy shared among all objects and are automatically given default values by the JVM.

Example:
class Test {
    static int x;

    public static void main(String... args) {
        System.out.println(x);   // output: 0
    }
}

If a static variable is declared as final, then explicit initialization is mandatory.

Example:
class Test {
    final static int x;
}

Compile-time Error: variable x might not have been initialized.

Rule: A final static variable must be initialized before class loading completes.

Possible places for initialization

1. At the time of declaration
class Test {
    final static int x = 10;
}
2. Inside a static block
class Test {
    final static int x;

    static {
        x = 10;
    }
}

These are the only valid places. Assigning anywhere else causes an error.

Invalid Example:
class Test {
    final static int x;

    public void m() {
        x = 10;   // Invalid
    }
}

Compile-time Error: cannot assign a value to final variable x.

Final Local Variables

If a variable is declared inside a method, constructor, or block, it is called a local variable.

  • Local variables must be initialized explicitly before use; the JVM does not provide default values.
  • If a local variable is declared as final, its value cannot be changed once assigned.
Example:
class Test {
    public static void main(String... args) {
        final int x;
        x = 10;
        System.out.println(x);   // output: 10
    }
}

Rule: A final local variable can be assigned only once, and it must be assigned before it is used.

Invalid Example:
class Test {
    public static void main(String... args) {
        final int x = 10;
        x = 20;   // Invalid, cannot reassign
        System.out.println(x);
    }
}

Compile-time Error: cannot assign a value to final variable x.

Another Invalid Example (used before assignment):
class Test {
    public static void main(String... args) {
        final int x;
        System.out.println(x);   // Invalid, x not yet assigned
        x = 10;
    }
}

Compile-time Error: variable x might not have been initialized.

Note: Unlike final instance and static variables, a final local variable does not need to be initialized at the time of declaration — but it must be assigned exactly once before it is read, and it cannot be reassigned afterward.

Conclusion

The core idea stays the same across all three: once you mark a variable final, the JVM stops giving you a free default value, and you become responsible for initializing it exactly once, in one of a small set of allowed places. Where those allowed places are is what differs:

  • Instance: declaration, instance block, or constructor — must be done before the constructor finishes.
  • Static: declaration or static block — must be done before class loading completes.
  • Local: anywhere in the method, as long as it happens exactly once, before the variable is read.

Get the initialization timing right, and final becomes a simple, useful way to guarantee a value never changes after it's set.

0 Comments