Codectionary / Developer documentation / Java

final Variables and Mutable Objects

Distinguish a variable that cannot be reassigned from an object whose contents cannot change.

What it is and why to use it

final limits assignment to a variable. Once a final variable has been assigned, code cannot assign it another value. For reference variables, this keeps the reference stable; it does not freeze the referenced object. This is useful when a collection should keep its identity while accumulating results.

How it works

The final list below remains the same list while add changes its contents. A final primitive such as limit stores a value that cannot be reassigned. Whether an object is immutable depends on its design and API, not just whether a reference to it is final.

Common mistakes and limitations

A final collection is not automatically thread-safe or deeply immutable. final methods and final classes have different roles: they prevent overriding and subclassing respectively. Do not infer those meanings from a final local variable.

Try it and keep learning

Save the complete example below as Main.java. With a JDK supporting Java 17, compile using javac --release 17 Main.java, then run java Main from the same directory. These examples need only the standard library and fixed input; they do not require packages, files or network access.

Syntax

final List<String> tasks = new ArrayList<>();

Examples

final Variables and Mutable Objects

Complete Main.java example — Java 17 or later, without preview features.

import java.util.ArrayList;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    final int limit = 2;
    final List<String> tasks = new ArrayList<>();
    tasks.add("Read");
    tasks.add("Practice");
    System.out.println(tasks);
    System.out.println(tasks.size() == limit);
  }
}
  1. limit is assigned 2 once, and tasks is assigned a new mutable list once.
  2. Both add calls are allowed because they mutate that list rather than reassign tasks.
  3. The printed list contains two tasks and the size comparison is true. Writing tasks = new ArrayList<>() afterward would be a compiler error.
  4. Expected output: [Read, Practice] true

Best practices

  • Use final when stable assignment clarifies intent.
  • Choose unmodifiable collections separately when changes must be prohibited.

Runtime & versions

Java Virtual Machine. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

Java Language Specification

Specifications & further reading