80

現在、いくつかの Java アプリケーションを実装していますが、これまでのところデスクトップ アプリケーションのみです。私は、JavaBeans とも呼ばれるミューテーター (セッターとゲッター)を持つオブジェクトを使用する代わりに、アプリケーション内でデータを渡すために不変オブジェクトを使用することを好みます。

しかし、Java の世界では、JavaBeans を使用する方がはるかに一般的であるように思われますが、代わりに JavaBeans を使用する必要がある理由がわかりません。個人的には、常に状態を変更するのではなく、不変オブジェクトのみを処理する方がコードの見栄えが良くなります。

不変オブジェクトは、項目 15: 可変性を最小化する、Effective Java 2edにも推奨されています。

JavaBeanPersonとして実装されたオブジェクトがある場合、次のようになります。

public class Person {
    private String name;
    private Place birthPlace;

    public Person() {}

    public setName(String name) {
        this.name = name;
    }

    public setBirthPlace(Place birthPlace) {
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

そして、不変オブジェクトPersonとして実装されたものと同じです:

public class Person {
    private final String name;
    private final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

structまたはCのに近い:

public class Person {
    public final String name;
    public final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }
}

実装の詳細を隠すために、不変オブジェクトにゲッターを含めることもできます。しかし、私はそれを単に使用するだけなのでstruct、「ゲッター」をスキップして単純にすることを好みます。

簡単に言えば、JavaBeans を使用する方が良い理由がわかりません。また、不変の POJO を使用し続けることができるかどうか、またそうする必要があるかどうかもわかりません。

Java ライブラリの多くは JavaBeans をより適切にサポートしているように見えますが、不変の POJO のサポートが徐々に普及していくのではないでしょうか?

4

7 に答える 7

79

次の場合は JavaBeans を優先

  • それらを期待する環境とやり取りする必要があります
  • インスタンス化時にすべての初期化を行うのが不便なプロパティがたくさんあります
  • なんらかの理由でコストがかかる、またはコピーが不可能であるが、ミューテーションが必要な状態がある
  • ある時点で、プロパティへのアクセス方法を変更する必要があると思われる場合 (たとえば、保存された値から計算された値への移行、アクセス許可など)。
  • JavaBeans を使用するほうが何らかの形でより「オブジェクト指向」であると無意識に主張するコーディング標準に準拠したい

不変の POJO を優先する場合

  • 少数の単純なプロパティがある
  • JavaBean 規約を想定した環境と対話する必要はありません
  • オブジェクトのクローンを作成するときに状態をコピーするのは簡単です(または少なくとも可能です)
  • オブジェクトのクローンを作成する予定はまったくありません
  • 上記のようにプロパティへのアクセス方法を変更する必要がないことは確かです
  • コードが十分に「オブジェクト指向」ではないことについての泣き言 (または嘲笑) を聞いても構いません。
于 2010-08-18T11:00:06.833 に答える
40

この議論のどこにもスレッドという言葉が出てこないことに驚きました。

不変クラスの主な利点の 1 つは、変更可能な共有状態がないため、本質的によりスレッド セーフであることです。

これにより、コーディングが容易になるだけでなく、副作用として次の 2 つのパフォーマンス上の利点も得られます。

  • 同期の必要性が少なくなります。

  • final 変数を使用する範囲が広がり、その後のコンパイラの最適化が容易になります。

JavaBean スタイルのクラスではなく、不変オブジェクトに移行しようとしています。ゲッターとセッターを介してオブジェクトの中身を公開することは、おそらくデフォルトの選択ではありません。

于 2010-08-18T11:29:33.470 に答える
19

まあ、それはあなたがやろうとしていることに依存します。永続層を使用していて、データベースから POJO に行をフェッチし、プロパティを変更して保存したい場合、特にプロパティが多数ある場合は、JavaBean スタイルを使用することをお勧めします。

あなたの人には、名、ミドルネーム、姓、生年月日、家族、学歴、仕事、給料などの多くのフィールドがあると考えてください.

そして、その人はたまたま結婚したばかりの女性で、姓の変更を受け入れたので、データベースを更新する必要があります。

不変の POJO を使用している場合は、彼女を表す Person オブジェクトをフェッチしてから、変更しなかったすべてのプロパティと新しい姓をそのまま渡す新しい Person オブジェクトを作成し、それを保存します。

Java Bean の場合は、setLastName() を実行して保存できます。

「可変オブジェクトを使用しない」ではなく、「可変性を最小限に抑える」ことです。状況によっては、変更可能なオブジェクトの方がうまく機能します。オブジェクトを変更可能にすることがプログラムに適しているかどうかを判断するのは、実際にはあなたの仕事です。「不変オブジェクトを使用する必要がある」と常に言うべきではありません。代わりに、自分を傷つけ始める前に、不変にすることができるクラスの数を確認してください。

于 2010-08-18T10:41:45.213 に答える
8

他の回答を要約すると、次のように思います。

  • 不変性により、正確性(構造体は参照によって渡すことができ、欠陥のある/悪意のあるクライアントによって何も破壊されないことがわかっています) とコードの単純さが促進されます。
  • 可変性は均一性を促進します。Springその他のフレームワークは、引数なしでオブジェクトを作成し、オブジェクトのプロパティを設定すると、ほら。また、データを提供し、変更を保存するために同じクラスを使用して、インターフェイスを簡単にします ( and は必要get(id): Clientありませんsave(MutableClient)。MutableClient は Client.

中間点 (作成、プロパティの設定、不変にする) があれば、フレームワークは不変のアプローチをより奨励するでしょう。

とにかく、不変オブジェクトを「読み取り専用の Java Beans」と考えることをお勧めします。あなたが善良な人であり、その危険な setProperty メソッドに触れなければすべて問題ないという点を強調します。

于 2010-08-18T11:29:55.893 に答える
3

Java 7 からは、両方の長所を備えた不変の Bean を使用できます。コンストラクターでアノテーション @ConstructorProperties を使用します。

public class Person {
    private final String name;
    private final Place birthPlace;

    @ConstructorProperties({"name", "birthPlace"})
    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}
于 2014-09-23T08:02:22.687 に答える
1

正直なところ、イミュータブル オブジェクトがこれほど普及するとは思いません。

確かに利点はわかりますが、Hibernate や Spring などのフレームワークは現在非常に流行しており (正当な理由もあります)、Bean との連携が最も優れています。

したがって、不変性が悪いとは思いませんが、現在のフレームワークとの統合オプションが制限されることは確かです。

編集コメントは、私の答えを少し明確にするように促します。

不変性が非常に有用で、実際に使用されている問題領域があることは間違いありません。しかし、現在のデフォルトは変更可能であるように思われると思います。それはほとんどの場合予想されることであり、明確な利点がある場合にのみ不変です。

そして、Spring で引数を使用してコンストラクターを使用することは実際に可能ですが、それは、美しい真新しい Spring コードでレガシーおよび/またはサードパーティのコードを使用する方法として意図されているようです。少なくともそれは私がドキュメントから拾ったものです。

于 2010-08-18T10:39:00.680 に答える