Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaの可変オブジェクト(Mutable)と不変オブジェクト(Immutable)の違いを徹底解説

Javaにおいて、不変オブジェクト(Immutable Object)とは、一度生成された後にその内部状態(フィールドの値)を変更できないオブジェクトのことを指します。ただし、他のオブジェクトへの参照自体は保持することができます。不変オブジェクトは、複数のスレッドから状態を書き換えられる心配がないため、マルチスレッド環境で特に有用であり、スレッドセーフであると言えます。さらに、時間的な結合(temporal coupling)を回避するのに役立ち、常に失敗時原子性(failure atomicity)を保証できるというメリットもあります。

一方、可変オブジェクト(Mutable Object)は、生成後に値を変更できるフィールドを持つオブジェクトです。つまり、インスタンス化した後もその状態を自由に書き換えることができます。対照的に、不変オブジェクトには生成後に変更できるフィールドが一切存在しません。

可変オブジェクトと不変オブジェクトの比較表

番号項目可変オブジェクト不変オブジェクト
1 基本 生成後にオブジェクトの状態を変更できる 生成後にオブジェクトの状態を変更できない
2 スレッドセーフ スレッドセーフではない スレッドセーフである
3 final修飾子 クラスをfinalにする必要はない 不変クラスを作るには、クラスをfinalとして宣言する
4 具体例 デフォルトでは、すべてのクラスとそのオブジェクトは本質的に可変である Stringや各種ラッパークラス(Integer、Booleanなど)が不変クラスの代表例

不変クラス(Immutable Class)の実装例

以下は、クラスをfinalで宣言し、setterを持たせずにコンストラクタでのみ値を設定することで、不変クラスを実現した例です。

public final class ImmutableClass {
    private String laptop;

    public String getLaptop() {
        return laptop;
    }

    public ImmutableClass(String laptop) {
        super();
        this.laptop = laptop;
    }
}

public class Main {
    public static void main(String args[]) {
        ImmutableClass immutableClass = new ImmutableClass("Dell");
        System.out.println(immutableClass.getLaptop());
    }
}

可変クラス(Mutable Class)の実装例

一方、以下の例ではsetterメソッド(setLaptop)を提供しているため、オブジェクト生成後もフィールドの値を変更できる可変クラスとなっています。

public class MutableClass {
    private String laptop;

    public String getLaptop() {
        return laptop;
    }

    public void setLaptop(String laptop) {
        this.laptop = laptop;
    }

    public MutableClass(String laptop) {
        super();
        this.laptop = laptop;
    }
}

public class Main {
    public static void main(String args[]) {
        MutableClass mutableClass = new MutableClass("Dell");
        System.out.println(mutableClass.getLaptop()); // Dell と出力

        mutableClass.setLaptop("IBM");
        System.out.println(mutableClass.getLaptop()); // IBM と出力
    }
}

このように、不変クラスは「クラスをfinalにする」「フィールドをprivateにする」「setterを提供しない」という設計原則に従うことで実現できます。状態が変わらないことでバグを防ぎやすく、並行処理でも安全に扱えるため、可能な限り不変オブジェクトを採用することが推奨されます。

  1. JavaにおけるComparableとComparatorの違いを徹底解説

    はじめに Javaでは、コレクション(Listなど)の要素を並べ替える際に、ComparableとComparatorという2つのインターフェースを使用できます。どちらもソートのためのインターフェースですが、役割や使い方には明確な違いがあります。 Comparableはjava.langパッケージに属し、「自分自身(this)」と引数で渡された1つのオブジェクトを比較することで、クラス固有の自然順序付けを定義します。一方、Comparatorはjava.utilパッケージに属し、比較対象となる2つのオブジェクトを受け取り、ソートのロジックを外部から柔軟に指定できるのが特徴です。 Compara

  2. Pythonのイテラブルとイテレータの違いをわかりやすく解説

    Pythonにおけるイテラブルとは、組み込み関数iter()に渡したときにイテレータを生成できるオブジェクトのことです。あるオブジェクトがイテラブルであるためには、いくつかの条件を満たす必要があります。具体的には、そのクラスのオブジェクトが__len__と__getitem__という2つのインスタンスメソッドを定義していなければなりません。これらの条件を満たすオブジェクトをiter()に渡すと、イテレータが生成されます。 それでは、以下の例でイテラブルの動きを確認してみましょう。 string = Tutorialspoint for char in string: print(ch