Menu
CoddyTech

finalキーワード

CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 13/87。

Javaのfinalキーワードは変更を防ぎます。変数、メソッド、クラスに適用でき、それぞれ異なる効果があります。

変数に適用すると、finalはその変数を定数にします。一度代入すると、その値は変更できません。

public class Circle {
    private final double PI = 3.14159;
    private final double radius;
    
    public Circle(double radius) {
        this.radius = radius;  // constructor 内で一度だけ代入できる
    }
    
    public void setRadius(double r) {
        // this.radius = r;  // エラー!final 変数には再代入できない
    }
}

final変数は、宣言時またはコンストラクター内で初期化する必要があります。その後、再代入しようとするとコンパイルエラーが発生します。

参照型の場合、finalは参照先を別のオブジェクトに変更できないことを意味しますが、オブジェクトの内容は変更できます。

private final StringBuilder name = new StringBuilder("John");

// name = new StringBuilder("Jane");  // エラー!再代入はできません
name.append(" Doe");  // OK!オブジェクトの内容は変更できます

フィールドにfinalを使用すると意図が明確に伝わります。初期化後、この値は決して変更されないことをほかの開発者に伝えます。これは、設定値、ID、またはオブジェクトの存続期間を通じて一定でなければならないあらゆるデータに特に役立ちます。

final メソッドはサブクラスでオーバーライドできません:

class Base {
    public final void greet() {
        System.out.println("Hi");
    }
}
class Child extends Base {
    // public void greet() { }  // エラー!greet() は Base で final として宣言されている
}

finalなクラスは一切拡張できません。Stringはfinalクラスなので、これを拡張できるクラスはありません。

final class Config { }
// class MyConfig extends Config { }  // エラー!Config は final です
challenge icon

チャレンジ

簡単

final キーワードを使って、学生の登録後に決して変更されるべきでないデータを保護する Student 登録システムを作りましょう。

コードを整理するために、2つのファイルを作成します。

  • Student.java:一度設定した特定の情報が永久に変更できない Student クラスを作成します。
    • final フィールド studentId (String) - 作成時に割り当てられ、変更できません
    • final フィールド enrollmentYear (int) - 学生が入学した年で、これも永久に変更できません
    • 通常の private フィールド name (String) - 学生が名前を変更した場合に更新できます
    • 3つすべての値を受け取り、フィールドを初期化するコンストラクター
    • 学生 ID を取得する getter getStudentId()
    • 入学年を取得する getter getEnrollmentYear()
    • 名前を取得する getter getName() と、名前を設定する setter setName()
    • "ID: [studentId] | Name: [name] | Enrolled: [enrollmentYear]" を返すメソッド getInfo()
  • Main.java:Student オブジェクトを作成し、名前を更新して情報を表示します。4つの入力を受け取ります。学生 ID、最初の名前、入学年、更新後の新しい名前です。次の2行を出力します。
    • 名前を変更する前の学生情報
    • 名前を変更した後の学生情報

入力は順に4つ受け取ります。studentId (String)、name (String)、enrollmentYear (int)、newName (String) です。

final フィールドによって学生の ID と入学年が保護される点に注目してください。これらは変更されるべきでない恒久的な記録ですが、名前は setter を通じて更新できます。

自分で試してみよう

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 入力を読み取る
        String studentId = scanner.nextLine();
        String name = scanner.nextLine();
        int enrollmentYear = scanner.nextInt();
        scanner.nextLine(); // 改行を読み飛ばす
        String newName = scanner.nextLine();
        
        // TODO: 初期値を使ってStudentオブジェクトを作成する
        
        // TODO: 名前を変更する前の学生情報を表示する
        
        // TODO: セッターを使って学生の名前を更新する
        
        // TODO: 名前を変更した後の学生情報を表示する
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Javaオンラインコンパイラ