Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Java Dictionary

  1. Home
  2. Java Dictionary
  3. final (Java)

final (Java)

A keyword that makes variables, methods, and classes "immutable" or "non-overridable". Applying final to a variable prevents reassignment; applying it to a method prevents overriding in subclasses; applying it to a class prevents inheritance. For constant definitions, combining static final is the conventional approach.

Syntax

// final local variable: cannot be reassigned once a value is set
final int MAX_LEVEL = 100;

// final field: initialized in the constructor or at the point of declaration
class Hero {
    final String name; // Initialized in the constructor

    Hero(String name) {
        this.name = name; // Can be assigned exactly once here
    }
}

// static final (class constant): conventionally named in UPPER_SNAKE_CASE
static final int MAX_POWER = 9000;

// final method: cannot be overridden in a subclass
final void specialMove() {
    // implementation
}

// final class: cannot be extended
final class Scouter {
    // implementation
}

Uses of final

TargetEffectCommon use
Local variableCannot be reassigned after declaration.Prevent unintended modification. Required for variables referenced inside a lambda expression.
FieldCannot be reassigned after the constructor completes.Designing immutable objects. Guaranteeing that a value does not change after initialization.
static final (constant)A class-level field that cannot be changed.Eliminating magic numbers. Giving a meaningful name to a constant value.
Method parameterThe parameter variable cannot be reassigned inside the method.Preventing accidental overwriting of arguments to reduce bugs.
MethodCannot be overridden in a subclass.Protecting behavior that must not be changed through inheritance.
ClassThe class cannot be extended.Guaranteeing immutability by design (e.g., the String class).

Sample Code

FinalVariable.java
public class FinalVariable {
    public static void main(String[] args) {

        // --- final local variable ---
        final String hero = "孫悟空";
        // hero = "ベジータ"; // Compile error: cannot reassign a final variable

        // --- static final constant ---
        // MAX_POWER is already defined as a class constant
        System.out.println(hero + "'s max power: " + Saiyan.MAX_POWER);

        // --- Using a class with final fields ---
        Saiyan s1 = new Saiyan("ベジータ", 8000);
        Saiyan s2 = new Saiyan("フリーザ", 12000);

        System.out.println(s1.name + ": " + s1.power);
        System.out.println(s2.name + ": " + s2.power);

        // s1.name = "ナッパ"; // Compile error: cannot modify a final field

        // --- final method parameter ---
        printStatus("クリリン", 1500);
    }

    // final parameter: prevents accidental reassignment of the argument inside the method
    static void printStatus(final String name, final int power) {
        // name = "亀仙人"; // Compile error: cannot reassign a final parameter
        System.out.println(name + "'s power is " + power + ".");
    }
}

// --- Class with static final constants and final fields ---
class Saiyan {

    // Class constants (static final): named in UPPER_SNAKE_CASE
    static final int MAX_POWER = 9000;
    static final String RACE   = "サイヤ人";

    // final fields: can be initialized exactly once in the constructor
    final String name;
    final int    power;

    Saiyan(String name, int power) {
        this.name  = name;
        this.power = power;
    }
}
javac FinalVariable.java
java FinalVariable
孫悟空's max power: 9000
ベジータ: 8000
フリーザ: 12000
クリリン's power is 1500.
FinalMethod.java
public class FinalMethod {
    public static void main(String[] args) {
        SuperSaiyan goku   = new SuperSaiyan("孫悟空");
        SuperSaiyan vegeta = new SuperSaiyan("ベジータ");

        goku.transform();   // Calls the overridden method in the subclass
        vegeta.transform();

        goku.kamehameha();  // final methods cannot be overridden
        vegeta.kamehameha();
    }
}

// Parent class
class Fighter {
    String name;

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

    // final method: cannot be overridden in a subclass
    final void kamehameha() {
        System.out.println(name + " fires a Kamehameha! (final method)");
    }

    // Regular method: can be overridden in a subclass
    void transform() {
        System.out.println(name + " is in base form.");
    }
}

// Subclass
class SuperSaiyan extends Fighter {

    SuperSaiyan(String name) {
        super(name);
    }

    // transform is not final, so it can be overridden
    @Override
    void transform() {
        System.out.println(name + " transformed into a Super Saiyan!");
    }

    // kamehameha is final, so attempting to override it causes a compile error
    // @Override
    // void kamehameha() { } // Compile error: cannot override a final method
}
javac FinalMethod.java
java FinalMethod
孫悟空 transformed into a Super Saiyan!
ベジータ transformed into a Super Saiyan!
孫悟空 fires a Kamehameha! (final method)
ベジータ fires a Kamehameha! (final method)
FinalClass.java
public class FinalClass {
    public static void main(String[] args) {
        DragonBall db = new DragonBall(7, "地球のドラゴンボール");
        System.out.println("Collect " + db.count + " of " + db.name + " to have your wish granted.");
        db.display();
    }
}

// final class: cannot be extended
final class DragonBall {
    final int    count;
    final String name;

    DragonBall(int count, String name) {
        this.count = count;
        this.name  = name;
    }

    void display() {
        System.out.println("[" + name + "] — " + count + " in total");
    }
}

// Attempting to extend DragonBall causes a compile error
// class NamekDragonBall extends DragonBall { } // Compile error: cannot inherit from final class
javac FinalClass.java
java FinalClass
Collect 7 of 地球のドラゴンボール to have your wish granted.
[地球のドラゴンボール] — 7 in total
EffectivelyFinal.java
import java.util.List;

public class EffectivelyFinal {
    public static void main(String[] args) {

        // --- Effectively final ---
        // The Java compiler treats a variable that is never modified after declaration
        // as "effectively final".
        // A lambda expression can only reference variables that are final or effectively final.

        String villain = "フリーザ"; // Not declared final, but never modified — effectively final

        // The lambda can reference the outer variable villain
        Runnable announcement = () ->
            System.out.println(villain + " is attacking!");

        announcement.run();

        // villain = "セル"; // Uncommenting this line causes a compile error on the lambda above
        // → "Variable used in lambda expression should be final or effectively final"

        // --- Example: print list elements with a lambda ---
        List<String> fighters = List.of("孫悟空", "ベジータ", "ピッコロ", "クリリン");

        // threshold is never modified, so it is effectively final
        int threshold = 5000;

        fighters.forEach(name -> {
            // name is a lambda parameter, so there is no issue
            System.out.println(name + " (power threshold: " + threshold + ")");
        });
    }
}
javac EffectivelyFinal.java
java EffectivelyFinal
フリーザ is attacking!
孫悟空 (power threshold: 5000)
ベジータ (power threshold: 5000)
ピッコロ (power threshold: 5000)
クリリン (power threshold: 5000)

Common Mistake 1: Applying final to a reference type still allows mutation of the object's internals

Applying final to a reference-type variable only prevents reassignment of the reference. The fields and contents of the referenced object can still be changed. Assuming that "making it final also freezes the contents" is a common source of bugs.

FinalRefNg.java
import java.util.ArrayList;

public class FinalRefNg {
    public static void main(String[] args) {
        // Even with final, the contents of the ArrayList can be changed
        final ArrayList<String> fighters = new ArrayList<>();
        fighters.add("孫悟空");
        fighters.add("ベジータ");

        // Elements can still be added despite final
        fighters.add("フリーザ");
        System.out.println(fighters); // [孫悟空, ベジータ, フリーザ]

        // Reassigning the reference causes a compile error
        // fighters = new ArrayList<>(); // NG: cannot assign a value to final variable
    }
}
javac FinalRefNg.java
java FinalRefNg
[孫悟空, ベジータ, フリーザ]

To also prevent modification of the contents, use Collections.unmodifiableList() or List.of() (Java 9+) to create an immutable list.

FinalRefOk.java
import java.util.List;
import java.util.Collections;
import java.util.ArrayList;

public class FinalRefOk {
    public static void main(String[] args) {
        // A list created with List.of() is unmodifiable (Java 9+)
        final List<String> fighters = List.of("孫悟空", "ベジータ", "ピッコロ");
        System.out.println(fighters);

        // fighters.add("フリーザ"); // Throws UnsupportedOperationException

        // For Java 8 and earlier, use Collections.unmodifiableList()
        ArrayList<String> src = new ArrayList<>();
        src.add("孫悟空");
        src.add("ベジータ");
        final List<String> immutable = Collections.unmodifiableList(src);
        System.out.println(immutable);
    }
}
javac FinalRefOk.java
java FinalRefOk
[孫悟空, ベジータ, ピッコロ]
[孫悟空, ベジータ]

Common Mistake 2: Violating the naming convention for static final constants

Constants defined with static final should conventionally be named in UPPER_SNAKE_CASE (all uppercase, words separated by underscores). Using lowercase camelCase compiles fine but makes it hard to distinguish constants from variables at a glance.

ConstNamingNg.java
public class ConstNamingNg {

    // Non-conventional naming (compiles but is hard to read)
    static final int maxPower = 9000;    // NG: indistinguishable from a variable
    static final String raceName = "サイヤ人"; // NG: does not look like a constant

    public static void main(String[] args) {
        System.out.println("Max power: " + maxPower);
        System.out.println("Race: " + raceName);
    }
}
javac ConstNamingNg.java
java ConstNamingNg
Max power: 9000
Race: サイヤ人

Naming static final constants in UPPER_SNAKE_CASE makes it immediately clear in code that they are constants, not variables.

ConstNamingOk.java
public class ConstNamingOk {

    // UPPER_SNAKE_CASE makes it obvious at a glance that these are constants
    static final int    MAX_POWER = 9000;
    static final String RACE_NAME = "サイヤ人";

    public static void main(String[] args) {
        System.out.println("Max power: " + MAX_POWER);
        System.out.println("Race: " + RACE_NAME);
    }
}
javac ConstNamingOk.java
java ConstNamingOk
Max power: 9000
Race: サイヤ人

Notes

The most fundamental use of final is defining constants with static final. By convention, constant names are written in UPPER_SNAKE_CASE (uppercase snake case). Replacing magic numbers with named constants makes the intent of code clearer and improves maintainability.

A class with final fields is useful for designing "immutable objects" whose state does not change after instantiation. Immutable objects are thread-safe and less prone to unexpected side effects. Java's String class is itself a final class.

"Effectively final" refers to a local variable that is never modified after its declaration, even without the explicit final keyword. To reference a local variable from inside a lambda expression, that variable must be final or effectively final. Attempting to modify the variable after it is referenced by a lambda causes a compile error.

For access modifiers and static, see public / private / protected / static / final. For inheritance, see extends / super / @Override. For lambda expressions, see Lambda Expressions / Method References.

If you find any errors or copyright issues, please .