カテゴリ: Javaのカプセル化 更新日: 2025/06/27

Javaの不変クラス(Immutableクラス)の作り方を完全ガイド!初心者でもわかる設計手法

148
Java の不変クラス(Immutable クラス)を作る方法

先生と生徒の会話形式で理解しよう

生徒

「先生、Javaで一度作ったオブジェクトの中身を変更できないようにする方法はありますか?」

先生

「はい、Javaでは不変クラス(Immutableクラス)を作成することで、オブジェクトの状態を変更できないようにできます。」

生徒

「具体的にはどうやって作るんですか?」

先生

「それでは、基本的な作り方を見ていきましょう!」

1. 不変クラス(Immutableクラス)とは?

1. 不変クラス(Immutableクラス)とは?
1. 不変クラス(Immutableクラス)とは?

Javaにおける不変クラス(Immutableクラス)とは、一度インスタンスを生成すると、その状態(フィールドの値)を変更できないクラスのことを指します。代表的な例として、Stringクラスがあります。Stringオブジェクトは生成後にその内容を変更することができません。

不変クラスを使用することで、以下のようなメリットがあります:

  • スレッドセーフ:状態が変わらないため、複数のスレッドから同時にアクセスしても安全です。
  • 予測可能性:オブジェクトの状態が変わらないため、バグの原因となる予期しない変更を防げます。
  • セキュリティ:外部からの不正な変更を防ぐことができます。

2. 不変クラスを作成するための基本ルール

2. 不変クラスを作成するための基本ルール
2. 不変クラスを作成するための基本ルール

Javaで不変クラスを作成するためには、以下のルールを守る必要があります:

  1. クラスをfinalとして宣言する:クラスの継承を禁止し、サブクラスによる状態変更を防ぎます。
  2. すべてのフィールドをprivate finalとして宣言する:外部からの直接アクセスと再代入を防ぎます。
  3. セッターメソッドを提供しない:フィールドの値を変更する手段を与えません。
  4. コンストラクタで全てのフィールドを初期化する:オブジェクト生成時に完全な状態を設定します。
  5. ミュータブルなオブジェクトをフィールドに持つ場合、防御的コピーを行う:外部からの変更を防ぐために、コピーを作成して保持します。

3. 不変クラスの基本的な実装例

3. 不変クラスの基本的な実装例
3. 不変クラスの基本的な実装例

以下は、Personクラスを不変クラスとして実装した例です。


public final class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

このクラスでは、nameageのフィールドがprivate finalとして宣言されており、セッターメソッドが存在しないため、オブジェクトの状態を変更することができません。

Javaをこれから始める人や、 オブジェクト指向の考え方を基礎から理解したい人には、 定番の入門書がこちらです。

スッキリわかるJava入門 第4版をAmazonで見る

※ Amazon広告リンク

4. ミュータブルなオブジェクトを含む場合の対処法

4. ミュータブルなオブジェクトを含む場合の対処法
4. ミュータブルなオブジェクトを含む場合の対処法

不変クラスのフィールドにDateListなどのミュータブルなオブジェクトを含む場合、外部からの変更を防ぐために防御的コピー(ディフェンシブコピー)を行う必要があります。

以下は、Dateオブジェクトを含む不変クラスの例です。


import java.util.Date;

public final class Event {
    private final String title;
    private final Date date;

    public Event(String title, Date date) {
        this.title = title;
        this.date = new Date(date.getTime()); // 防御的コピー
    }

    public String getTitle() {
        return title;
    }

    public Date getDate() {
        return new Date(date.getTime()); // 防御的コピー
    }
}

このように、コンストラクタとゲッターメソッドで防御的コピーを行うことで、外部からのDateオブジェクトの変更がEventオブジェクトに影響を与えることを防ぎます。

5. コレクションを含む不変クラスの実装例

5. コレクションを含む不変クラスの実装例
5. コレクションを含む不変クラスの実装例

コレクション(ListMapなど)をフィールドに持つ場合も、防御的コピーを行う必要があります。以下は、StudentクラスがList<String>coursesフィールドを持つ例です。


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

public final class Student {
    private final String name;
    private final List<String> courses;

    public Student(String name, List<String> courses) {
        this.name = name;
        this.courses = new ArrayList<>(courses); // 防御的コピー
    }

    public String getName() {
        return name;
    }

    public List<String> getCourses() {
        return Collections.unmodifiableList(courses); // 不変のリストを返す
    }
}

この実装では、コンストラクタでcoursesリストのコピーを作成し、ゲッターメソッドでは不変のリストを返すことで、外部からの変更を防いでいます。

6. Java 14以降のrecordを使った不変クラスの作成

6. Java 14以降のrecordを使った不変クラスの作成
6. Java 14以降のrecordを使った不変クラスの作成

Java 14以降では、recordキーワードを使用することで、簡潔に不変クラスを作成できます。recordは以下の特徴を持ちます:

  • finalクラスとして自動的に定義される
  • すべてのフィールドがprivate finalとして定義される
  • コンストラクタ、ゲッター、equals()hashCode()toString()メソッドが自動生成される

以下は、Personクラスをrecordで定義した例です。


public record Person(String name, int age) {
}

このように、recordを使用することで、ボイラープレートコードを減らし、簡潔に不変クラスを定義できます。

7. 不変クラスの活用例とメリット

7. 不変クラスの活用例とメリット
7. 不変クラスの活用例とメリット

不変クラスは、以下のような場面で活用されます:

  • マルチスレッド環境:スレッドセーフなオブジェクトとして使用できます。
  • キャッシュのキー:状態が変わらないため、ハッシュコードが一定であり、キャッシュのキーとして適しています。
  • セキュリティ:外部からの不正な変更を防ぐことができます。

また、不変クラスを使用することで、コードの可読性と保守性が向上し、バグの発生を抑えることができます。

Javaのカプセル化の一覧へ
新着記事
FlutterのMVP・MVVMアーキテクチャの違いと使い分け
FlutterのMVP・MVVMアーキテクチャの違いと使い分けを初心者向けに解説!
オニオンアーキテクチャの基本とFlutterでの適用例
オニオンアーキテクチャの基本とFlutterでの適用例を初心者向けに解説
クリーンアーキテクチャとは?Flutterでの導入メリット
クリーンアーキテクチャとは?Flutterでの導入メリットをやさしく解説
【AWS】RDS for Oracleの特徴・できないこと・バージョン・料金まとめ
【AWS】RDS for Oracleの特徴・できないこと・バージョン・料金を初心者向けに徹底解説
人気記事
インスタンスタイプの料金比較と最適な選び方(最新2025年版)
AWSのインスタンスタイプの料金比較と最適な選び方【2025年最新版】
【AWS】VPCの料金体系まとめ!無料枠・通信費・各種サービスごとの料金を徹底解説
【AWS】VPCの料金体系まとめ!無料枠・通信費・各種サービスごとの料金を徹底解説
【AWS】VPCエンドポイントとは?種類・使い方・S3連携まで完全解説
【AWS】VPCエンドポイントとは?種類・使い方・S3連携まで完全解説
【AWS】s3 cpコマンド完全ガイド!基本・recursive・exclude/includeも解説
【AWS】s3 cpコマンド完全ガイド!基本・recursive・exclude/includeも解説

🔌 USBポート不足を解消

Type-C 1本で拡張。
開発・作業環境を一気に快適に

UGREEN USB-Cハブを見る

※ Amazon広告リンク