Menu
Coddy logo textTech

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;  // コンストラクタで一度だけ代入可能
    }
    
    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、またはオブジェクトの存続期間を通じて一定である必要があるデータに特に役立ちます。

challenge icon

チャレンジ

簡単

学生が登録された後に変更すべきではないデータを保護するために、finalキーワードを使用したStudent登録システムを構築しましょう。

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

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

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

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

チートシート

Javaにおいて、finalキーワードは変更を防止するために使用されます。これは変数、メソッド、およびクラスに適用できます。

変数に適用された場合、finalはその変数を持続的な定数にします。一度代入されると、その値を変更することはできません。

public class Circle {
    private final double PI = 3.14159;
    private final double radius;
    
    public Circle(double radius) {
        this.radius = radius;  // コンストラクタ内で一度だけ代入可能
    }
    
    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、または定数データに役立ちます。

自分で試してみよう

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腕試し

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

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