5

不変型にコピー メソッドを実装し、新しいインスタンスを返すことは理にかなっていますか? それとも、現在のインスタンスにする必要がありますか?

どうせタイプは変わらないと思っていたのになんでコピーするの?誰も5番をコピーしないようにね。

4

6 に答える 6

12

それが理にかなっている特定のケースがあります。Java 文字列が良い例です。文字列が Java で作成されると、文字のバッキング配列 (a char[]) への参照が含まれます。char配列へのオフセットと文字列の長さを知っています。部分文字列を作成すると、それは同じバッキング配列を参照します。次のコードを検討してください。

String x = buildVeryLongString();
String y = x.substring(0, 5);
// Use y a lot, but x is garbage collected

がまだシステムにあるということは、によって使用されyたオリジナルがまだ必要であることを意味します。つまり、必要以上のメモリを使用しています。コードを次のように変更した場合:char[]x

String x = buildVeryLongString();
String y = new String(x.substring(0, 5));

その後、データを新しい にコピーすることになりますchar[]xyの寿命がほぼ同じである場合、このアプローチは (2 つのコピーを持つことによって) メモリを浪費しますが、 が のx前にガベージ コレクションされる場合y、大きな違いが生じる可能性があります。

辞書から単語を読み取るときに、実際の文字列で同様の例に出くわしました。デフォルトでBufferedReader.readLine()は、 は行の開始に 80 文字のバッファを使用します。そのため、 によって返される (空でない) 文字列は、少なくとも 80 文字readLine()の配列を参照します。char[]1 行に 1 単語の辞書ファイルを読んでいる場合、それは多くの無駄なスペースです!

これは単なる例ですが、2 つの不変オブジェクトの違いを示しています。2 つの不変オブジェクトは意味的には同じですが、他の点では異なる特性を持っています。これは通常、不変型をコピーしたい理由の中心にありますが、それでもやりたいことはかなりまれです。

.NET では、文字列の格納方法が多少異なります。文字データは、別の配列ではなく、文字列オブジェクト自体に保持されます。IntPtr(私が知る限り、.NET で可変サイズの型は配列、文字列、および3 つだけです。)ただし、文字列の "バッファー" は必要以上に大きくなる可能性があります。例えば:

StringBuilder builder = new StringBuilder(10000);
builder.Append("not a lot");
string x = builder.ToString();

によって参照される文字列オブジェクトxには、巨大なバッファがあります。最後の行を に変更するbuilder.ToString().Copy()と、大きなバッファーがすぐにガベージ コレクションの対象になり、代わりに小さな文字列が残ります。繰り返しますが、これを無条件に行うのは悪い考えですが、場合によっては役に立ちます。

于 2009-06-06T20:04:55.620 に答える
4

技術的には、整数は値型であるため、常にコピーされます。:)

とはいえ、不変オブジェクトのコピーを作成しても意味がありません。他の人が提供する文字列の例は、それらのクラスによる抽象化の漏れに対する応急処置のようです。

于 2009-06-06T20:03:49.910 に答える
3

オブジェクト (クラス) を意味していると仮定します。

不変オブジェクトのクローンを作成するには、いくつかの疑わしい理由があります。

  • オブジェクトがremotedであり、ローカル コピーが必要な場合 (ただし、この場合、おそらくオブジェクト自体でインスタンス メソッドを使用することはできません。これは、リモートインスタンス返すためです。クローン メソッドをローカルにする必要があります)。 (非リモート))
  • リフレクションについて非常に心配している場合(リフレクションreadonlyによってフィールドさえも変更される可能性があります)-おそらく、いくつかの超セキュリティ意識の高いコードの場合
  • 一部の外部 API (制御できない) が参照の等価性を使用していて、同じ「値」を 2 つの別個のキーとして使用したい場合 - OK、私は今物事を拡張しています...

通常の不変オブジェクトは、関連付けられたオブジェクトも不変であることを意味しないため、議論を拡張してディープクローニングを検討すると、より合理的になります。ディープ クローンはこれを修正しますが、別の考慮事項です。

おそらくリモートシナリオが私ができる最善のことだと思います...

于 2009-06-06T20:29:05.150 に答える
2

Java の String クラスには次のようなものがあります。

String(String original)
      Initializes a newly created String object so that it represents the same 
      sequence of characters as the argument; in other words, the newly created 
      string is a copy of the argument string.

そして.NetにCopy()は同じことをするメソッドがあります。

両方のフレームワークは私より賢い人によって設計されたので、正当な理由があるに違いありません - 誰かが参照に関して異なるが同じ値を持つ文字列を必要とすることがあります。

それがいつになるかはわかりません...

于 2009-06-06T20:04:43.357 に答える
2

不変オブジェクトに「コピー」操作を提供することは理にかなっていますか?

いいえ。

(他の回答には他にも興味深い議論がたくさんありますが、短い回答を提供すると思いました。)

オブジェクトが Clone() メソッド (または同等のメソッド) を必要とするインターフェースを実装する必要がある場合は、「これを返す」ことは問題ありません。

于 2009-06-06T20:18:29.243 に答える
0

不変型の利点の 1 つは、インターンできることです (Java 文字列など)。避けられるのであれば、確かに余分なコピーを作成するべきではありません。

于 2009-06-06T19:52:15.583 に答える