不変オブジェクトは常に同じ状態、つまり実際に作成された状態であることを私は知っています。それらの不変条件はコンストラクターによって確立され、それらの状態は構築後に変更されないため、これらの不変条件は常に有効であり、これがマルチスレッド環境で安全に公開できる理由です。これはすべて問題ありませんが、プログラムの状態が絶えず変化する動的な世界に住んでいるため、不変オブジェクトを介してプログラムの状態を構築すると、そのようなオブジェクトはどのような利点をもたらすでしょうか?
4 に答える
「そのようなオブジェクトは私たちにどのような利益をもたらしますか」あなたはすでに答えました。
質問の「動的」部分に関して、不変オブジェクトを「変更」する必要がある場合は、古いオブジェクトから新しいオブジェクトを作成できます。
Immutable oldObj = new Immutable(...);
Immutable newObj = new Immutable(oldObj.property1, "a new value for property 2");
これを繰り返し行う場合は、オブジェクトを変更可能にして、並行環境でそのオブジェクトを使用できるようにするために必要な、関連するトレッド セーフティ機能を追加する必要があるかもしれません。
不変オブジェクトを使用すると、状態の変化をさまざまなスレッドにクリーンに伝達できます。
スレッド間で交換されるメッセージを表すために不変オブジェクトを使用することをお勧めします。このようなメッセージが送信されると、そのペイロードを変更できないため、同時実行に関連する多くのバグが防止されます。スレッドがさらに変更を伝達する必要がある場合は、次のメッセージを送信するだけです。
不変オブジェクトは、次のような場合に非常に便利です。String オブジェクトを使用すると、次のようになります。
public class A {
private volatile String currentName = "The First Name";
public String getCurrentName() {
// Fast: no synching or blocking! Can be called billions of times by
// billions of threads with no trouble.
// (Does need to be read from memory always because it's volatile.)
return currentName;
}
public whatever someMethod() {
... code ...
// Simple assignment in this case. Could involve synchronization
// and lots of calculations, but it's called a lot less than
// getCurrentName().
currentName = newName;
... code ...
}
}
public class B {
... in some method ...
A objA = something;
// Gets "name" fast despite a billion other threads doing the same thing.
String name = objA.getCurrentName();
// From this point on, String referenced by "name" won't change
// regardless of how many times A.currentName changes.
... code with frequent references to objA
}
これにより、一貫性が必要な複雑なデータ (この場合は単純なデータでさえ) (正確に最新でなくても) を更新し、必要な人に非常に迅速かつスレッドセーフな方法で配信できます。配信されたデータはおそらくすぐに古くなりますが、メソッドの呼び出し中にその値を保持し、一貫性を保ちます。
Immutable objects
状態が決して変わらない静的オブジェクトが必要な場合に非常に役立ちます。暗黙のうちに、これは並行性の存在下での決定論的な動作も意味します。
Java では、 のようないくつかの不変クラスが既に定義されていますString
Integer
。
その他の利点は、常に「失敗原子性」(Joshua Bloch が使用する用語) を持っていることです。不変オブジェクトが例外をスローした場合、望ましくない状態や不確定な状態になることはありません。
国コードのような静的オブジェクトのグローバル キャッシュがある場合、ここで適用できますImmutability
。