8

私はしばらくの間グアバを使用していて、昨日例に出くわすまで、それを本当に信頼していました。それは私に考えさせられました。簡単に言えば、ここにあります:

 public static void testGuavaImmutability(){
     StringBuilder stringBuilder = new StringBuilder("partOne");
     ImmutableList<StringBuilder> myList = ImmutableList.of(stringBuilder);
     System.out.println(myList.get(0));
     stringBuilder.append("appended");
     System.out.println(myList.get(0));
 }

これを実行した後、 ImmutableList内のエントリの値が変更されたことがわかります。ここに2つのスレッドが含まれている場合、一方が他方の更新を確認できない可能性があります。

また、私が答えを非常に待ち焦がれているのは、Effective JavaのItem15、ポイント5が次のように言っていることです。

コンストラクターで防御コピーを作成します-これはかなり論理的なようです。

ImmutableListのソースコードを見ると、次のようになっています。

 SingletonImmutableList(E element) {
     this.element = checkNotNull(element);
 }

したがって、実際にはコピーは作成されませんが、そのような場合に一般的なディープコピーがどのように実装されるかはわかりません(シリアル化の可能性がありますか?)。

それで..なぜ彼らは不変と呼ばれるのですか?

4

3 に答える 3

28

ここで得ているのは、不変深く不変の違いです。

不変オブジェクトは決して変更されませんが、それが参照するものはすべて変更される可能性があります。基本オブジェクトも、そこからナビゲートできるオブジェクトも変更されません。

それぞれが独自の状況に適しています。type のフィールドを持つ独自のクラスを作成するとDate、その日付はオブジェクトによって所有されます。それは本当にその一部です。したがって、深い不変性を提供するために、(出入りする途中で!)防御的なコピーを作成する必要があります。

しかし、コレクションはその要素を実際に「所有」しているわけではありません。それらの状態は、コレクションの状態の一部とは見なされません。これは別のタイプのクラス、つまりコンテナです。(さらに、あなたがほのめかしたように、どの要素タイプが使用されているかについての深い知識がないため、とにかく要素をコピーする方法がわかりません。)

別の回答では、Guava コレクションではunmodifiableという用語を使用する必要があったと述べています。しかし、コレクションのコンテキストでは、変更不可不変という用語の間には明確に定義された違いがあり、浅い不変性と深い不変性とは何の関係もありません。「変更不可」は、参照を介してこのインスタンスを変更できないことを示しています「不変」とは、このインスタンスが、あなたまたは他のアクターによって変更できないことを意味します。

于 2012-08-21T14:08:22.387 に答える
12

要素を追加/削除できないため、リスト自体は不変です。要素は、不変性に関して独自のものです。より正確に言えば、歴史的な Java 1.4.2 ドキュメントからの定義があります。

  • 変更操作 (追加、削除、クリアなど) をサポートしないコレクションは、変更不可と呼ばれます。変更不可能でないコレクションは、変更可能と呼ばれます。
  • Collection オブジェクトの変更が表示されないことをさらに保証するコレクションは、不変と呼ばれます。不変ではないコレクションは、可変と呼ばれます。

これらの定義が意味を成すためには、抽象的な意味でのコレクションとそのコレクションを表すオブジェクトとの間の暗黙の区別を仮定する必要があることに注意ください。不変コレクションを表すオブジェクト自体は、その用語の標準的な定義では不変ではないため、これは重要です。たとえば、そのequals関係には一時的な一貫性がありません。これは、不変オブジェクトの重要な要件です。

防御的コピーに関する限り、これは一般的に不明確な問題であり、Java には、その要素を防御的にコピーする一般的な不変コレクションは決して存在しないことに注意してください。さらに、そのようなコレクションは、実際に存在する不変のコレクションよりも有用性が低いことに注意してください。オブジェクトをコレクションに入れるとき、99.99% のケースで、そのオブジェクトそのものがそこにあることを望みます。それ。

不変オブジェクトから到達可能なオブジェクトグラフ全体の推移的不変性を前提とする、(コレクションの不変性とは対照的に)オブジェクトの不変性の非常に標準的な定義があります。ただし、文字通りに捉えすぎると、そのような定義が現実の世界で満たされることはほとんどありません。適切な 2 つのケース:

  • 熟考に直面して不変のものはありません。finalフィールドも書き込み可能です。
  • でさえString、その不変性の砦は、Java サンドボックスの外部で変更可能であることが証明されていSecurityManagerます (実世界の Java プログラムの 99% をカバーする — なしで)。
于 2012-08-21T11:37:49.070 に答える
3

リストの不変性とそれに含まれるオブジェクトの不変性を組み合わせます。不変のコレクションでは、オブジェクトを追加/削除することはできませんが、含まれているオブジェクトが変更可能な場合は、それらをget()ing した後に変更できます。

于 2012-08-21T11:40:55.977 に答える