9

不変クラスがスケーラビリティを向上させ、可能な限り不変クラスを作成することをお勧めする設計書を読んだことがあります。しかし、不変クラスはオブジェクトの増殖を増加させると思います。では、スケーラビリティを向上させるために、不変クラスを使用するのが良いですか、それとも静的クラス (すべてのメソッドが静的なクラス) を使用する方が良いでしょうか?

4

8 に答える 8

16

ただし、不変クラスの主な利点は、呼び出し元が変更できないために不変である内部データ メンバーを公開できることです。これは、たとえば、 の大きな問題java.util.Dateです。これは可変であるため、メソッドから直接返すことはできません。これは、あらゆる種類の防御的コピーを行うことになることを意味します。これにより、オブジェクトの増殖が増加します。

もう 1 つの主な利点は、定義上、不変オブジェクトには同期の問題がないことです。ここでスケーラビリティの問題が発生します。マルチスレッドコードを記述するのは困難です。不変オブジェクトは、(ほとんどの場合) 問題を回避する良い方法です。

「静的クラス」に関しては、あなたのコメントでは、ファクトリメソッドを持つクラスを意味すると考えています。これは、通常の説明です。関係ないパターンです。可変クラスと不変クラスの両方に、静的ファクトリ メソッドを持つパブリック コンストラクターまたはプライベート コンストラクターを含めることができます。可変クラスは作成後に状態を変更できるクラスであるのに対し、不変クラスの状態はインスタンス化後に変更できないため、クラスの (不) 可変性には影響しません。

ただし、静的ファクトリ メソッドには他の利点もあります。アイデアは、オブジェクトの作成をカプセル化することです。

于 2009-08-16T16:47:45.453 に答える
5

不変クラスは確かにオブジェクトの増殖を促進しますが、安全性が必要な場合、可変オブジェクトはより多くのオブジェクトの増殖を促進します。これは、元のオブジェクトではなくコピーを返して、ユーザーが返すオブジェクトを変更できないようにする必要があるためです。

すべての静的メソッドでクラスを使用することに関しては、不変性を使用できるほとんどの場合、実際にはオプションではありません。RPG から次の例を取り上げます。

public class Weapon
{
    final private int attackBonus;
    final private int accuracyBonus;
    final private int range;

    public Weapon(int attackBonus, int accuracyBonus, int range)
    {
        this.attackBonus = attackBonus;
        this.accuracyBonus = accuracyBonus;
        this.range = range;
    }

    public int getAttackBonus() { return this.attackBonus; }
    public int getAccuracyBonus() { return this.accuracyBonus; }
    public int getRange() { return this.range; }
}

静的メソッドのみを含むクラスでこれをどのように実装しますか?

于 2009-08-16T19:43:57.947 に答える
1

考慮すべき 1 つの点: クラスのインスタンスを HashMap のキーとして使用する場合、またはそれらを HashSet に入れる場合は、それらを不変にする方が安全です。

HashMap と HashSet は、オブジェクトがマップまたはセット内にある限り、オブジェクトのハッシュ コードが一定であるという事実に基づいています。オブジェクトを HashMap のキーとして使用する場合、またはオブジェクトを HashSet に入れ、オブジェクトの状態を変更して hashCode() が別の値を返す場合、HashMap または HashSet とあなたは奇妙なものを手に入れるでしょう。たとえば、マップを繰り返したり、オブジェクトを設定したりすると、そこにあるのに、それを取得しようとすると、あたかもそこにないかのようになります。

これは、HashMap と HashSet が内部でどのように機能するかによるものです。これらはオブジェクトをハッシュ コードで整理します。

Java 並行処理の第一人者である Brian Goetz によるこの記事では、不変オブジェクトの長所と短所について概要を説明しています。

于 2009-08-16T18:44:45.857 に答える
1

cletusが言ったように、不変クラスはクラスの設計と同期メソッドでの処理を簡素化します。

また、シングルスレッド アプリケーションであっても、コレクションでの処理が簡素化されます。不変クラスは決して変更されないため、キーとハッシュコードは変更されないため、コレクションを台無しにすることはありません。

ただし、モデル化するもののライフサイクルとコンストラクターの「重み」に留意する必要があります。何かを変更する必要がある場合、不変オブジェクトの処理はより複雑になります。それらを変更するのではなく、交換する必要があります。ひどいものではありませんが、検討する価値があります。また、コンストラクターに多大な時間がかかる場合、それも要因です。

于 2009-08-16T17:08:44.560 に答える
0

同じオブジェクトを異なる変数間で共有したい場合は、不変である必要があると思います。

例えば:

String A = "abc";
String B = "abc";

Javaの文字列オブジェクトは不変です。これで、AとBの両方が同じ「abc」文字列を指します。今

A = A + "123";
System.out.println(B);

次のように出力されます。

abc

文字列は不変であるため、Aは、前の文字列オブジェクトを変更する代わりに、新しい「abc123」文字列オブジェクトを指すだけです。

于 2009-08-17T04:39:37.090 に答える
0

例として、文字列オブジェクトを考えてみましょう。変更可能な文字列を提供する言語またはクラス ライブラリもあれば、そうでないものもあります。

不変文字列を使用するシステムは、可変文字列を使用するシステムではできない特定の最適化を行うことができます。たとえば、一意の文字列のコピーが 1 つだけであることを確認できます。オブジェクトの「オーバーヘッド」のサイズは通常、重要な文字列のサイズよりもはるかに小さいため、これはメモリを大幅に節約できる可能性があります。部分文字列のインターンなど、他の潜在的なスペース節約があります。

不変オブジェクトは、潜在的なメモリの節約に加えて、競合を減らすことでスケーラビリティを向上させることができます。同じデータにアクセスするスレッドが多数ある場合、不変オブジェクトは安全なアクセスのために複雑な同期プロセスを必要としません。

于 2009-08-16T17:45:00.713 に答える
0

この件に関して、もう 1 つ考慮事項があります。不変オブジェクトを使用すると、それらをキャッシュし、毎回再作成する必要がなくなります (つまり、文字列)。アプリケーションのパフォーマンスが大幅に向上します。

于 2009-08-16T17:52:33.707 に答える
0

不変性は一般に、スケーラビリティを実現するために使用されます。これは、Java での並行プログラミングに関しては、不変性がイネーブラーの 1 つであるためです。したがって、ご指摘のとおり、「不変」ソリューションにはより多くのオブジェクトが存在する可能性がありますが、同時実行性を向上させるために必要なステップである可能性があります。

不変性のもう 1 つの同様に重要な用途は、設計意図を消費することです。不変クラスを作成した人は誰でも、可変状態を別の場所に置くことを意図していました。そのクラスのインスタンスを変更し始めると、おそらく設計の当初の意図を破ることになります。そして、その結果がどうなるかは誰にもわかりません。

于 2009-08-16T17:25:36.110 に答える