不変オブジェクトとは、作成後に状態を変更できないオブジェクトです。主な特性は以下の通りです:
不変オブジェクトの利点:
不変クラスの実装例:
public final class Person { private final String name; private final int age; private final List<String> phones; public Person(String name, int age, List<String> phones) { this.name = name; this.age = age; // 渡されたリストの変異からの保護 this.phones = Collections.unmodifiableList(new ArrayList<>(phones)); } public String getName() { return name; } public int getAge() { return age; } public List<String> getPhones() { return phones; } // 読み取り専用リストを返す }
なぜJavaのStringは不変であるのか、もしそうでなかったらどうなるか?多くの人は「安全のため」と答えますが、それは実際にはどういう意味でしょうか?
回答:
Stringは多くの場所で使用されます:コレクションのキーとして、安全性のロジック(例えば、パスワード)で。もし1つの参照を通じて文字列を変更できた場合、それは同じオブジェクトへの他のすべての参照に影響を与え、コレクションが正しく機能することが不可能になります(例えば、HashMap — hashCodeの計算時に)し、セキュリティ上の脆弱性を引き起こす可能性があります。
物語
Collections.unmodifiableListを返却するようになるまで問題が続きました。物語
Date、List)が保存されていました。1つのスレッドで設定が変更され、別のスレッドで古いまたは一貫性のないデータを取得したため、ビジネスアルゴリズムが正しく作動しませんでした。物語
ログインシステムでパスワードが可変オブジェクトに保存されていました。安全でないアクセスにより別のユーザーのパスワードが突然「漏洩」することになりました。同じオブジェクトのインスタンスが複数のスレッドで使用されていたためです。