【初心者向け】Javaで「イミュータブルクラス」を作る方法をやさしく解説!


イミュータブルクラスとは?

イミュータブル(Immutable)という言葉は、「変えられない」という意味です。
つまり「イミュータブルクラス」とは、作った後に状態(データ)が変わらないクラスのことを指します。

たとえば、文字列を扱うStringクラスもイミュータブルです。Stringオブジェクトを一度作ったら、あとから中身を変更することはできません。

なぜイミュータブルクラスを作るのか?
大きなメリットは以下です!

メリット説明
スレッドセーフ複数のスレッドから同時に使っても問題が起きにくい
バグが減る予期しないデータ変更が起きないので、安全
設計がシンプル状態管理を考える手間が少なくなる

たとえば、コップに水を入れる例で考えると、イミュータブルなコップは水が蒸発したり、量が変わったりしない魔法のコップです!


Javaでイミュータブルクラスを作る5つのルール

イミュータブルクラスを作るには、守るべき基本ルールがあります。

  1. クラスをfinalにする
    ⇒ サブクラスを作らせない!(サブクラスで状態を変えられる危険を防ぐ)
  2. フィールドもfinalにする
    ⇒ フィールド(メンバ変数)を一度だけ設定して、それ以降変更できないようにする。
  3. フィールドはprivateにする
    ⇒ 外から直接アクセスできないようにする。
  4. コンストラクタで全フィールドを初期化する
    ⇒ 作るときにすべてのデータを確定させる。
  5. ミュータブルなオブジェクト(例:リスト)を持つ場合は防御的コピーをする
    ⇒ 渡すときも、受け取るときもコピーして別物にする!

コード例:シンプルなイミュータブルクラス

それでは実際にコードを書いてみましょう。

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;
    }
}

ポイントを整理すると…

  • final class:クラス自体が継承できない
  • private final:フィールドも変更できない
  • コンストラクタで全部初期化
  • ゲッターは値を返すだけ(オブジェクトを変えない)

このようにすれば、作ったあとのPersonは二度と変更できません!


注意すべきポイント:ミュータブルなフィールドがある場合

例えば、リスト(List)のような中身が変わるオブジェクトを持つ場合は注意が必要です!

悪い例

public final class Team {
    private final List<String> members;

    public Team(List<String> members) {
        this.members = members; // 危険!!
    }

    public List<String> getMembers() {
        return members; // 外から変更される危険!
    }
}

この場合、外部からgetMembers().add("新しいメンバー")などされると、中身が変わってしまいます。

良い例(防御的コピー)

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

public final class Team {
    private final List<String> members;

    public Team(List<String> members) {
        this.members = new ArrayList<>(members); // コピー!
    }

    public List<String> getMembers() {
        return Collections.unmodifiableList(members); // 変更不可リストを返す
    }
}

こうすれば、外からリストをいじられることがありません!
まるで、オリジナルのリストを厳重なショーケースに入れるようなイメージですね!


イミュータブルクラスのメリット・デメリット

メリットまとめ

  • スレッドセーフで安心
  • コードの見通しが良くなる
  • バグの温床になる「状態変化」がない

デメリットまとめ

  • 変更するたびに新しいオブジェクトを作るので、メモリを多く使うことがある
  • 作成コスト(オブジェクト生成)が増える場合もある

たとえば、毎秒何万件ものデータを高速で扱う必要がある場面では、イミュータブルばかりにすると逆にパフォーマンスが落ちることもあります。


まとめとこれからの学び方

イミュータブルクラスは、「安全でシンプルなプログラム」を作るための新人エンジニアにとって強力な武器です!
まずは小さなクラスからイミュータブルにする練習をしてみましょう。

セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。