私はいくつかのJava=アプリケーションを実装しました。これまでのところデスクトップアプリケーションのみです。アプリケーションでデータを渡すために不変オブジェクトを使用する方が、ミューテーター(セッターおよびgetter)、JavaBeansとも呼ばれます。
しかし、Javaの世界では、JavaBeansを使用する方がはるかに一般的であるように思われ、なぜそれらを代わりに使用する必要があるのか理解できません。常に状態を変化させるのではなく、オブジェクト。
不変オブジェクトはアイテム15:可変性の最小化、Effective Java 2edでも推奨されています。
オブジェクトPerson
をJavaBeanとして実装すると、次のようになります。
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
がimmutableオブジェクトとして実装されています:
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;
}
}
またはCのstruct
に近い:
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のサポートが増えるにつれて、時間の経過とともに人気が高まるのではないでしょうか?
Threadという言葉がこのディスカッションのどこにも現れていないことに驚きました。
不変クラスの主な利点の1つは、変更可能な共有状態がないため、本質的にスレッドセーフであるということです。
これにより、コーディングが簡単になるだけでなく、副作用として2つのパフォーマンス上の利点も得られます。
同期の必要性が少なくなります。
後続のコンパイラー最適化を容易にすることができるfinal変数を使用するためのより多くのスコープ。
私は本当にJavaBeanスタイルのクラスではなく不変のオブジェクトに向かって動いています。ゲッターとセッターを介してオブジェクトの内部を公開することは、おそらくデフォルトの選択ではないはずです。
まあそれはあなたがやろうとしていることに依存します。永続的なレイヤーで作業していて、データベースからPOJOに行をフェッチし、プロパティを変更して保存したい場合は、特に多くのプロパティがある場合、JavaBeanスタイルを使用する方が良いでしょう。
あなたの人が、ファーストネーム、ミドルネーム、姓、生年月日、家族、教育、仕事、給与などの多くのフィールドを持っていると考えてください。
そして、その人はたまたま結婚し、彼女の姓を変更することを受け入れたばかりの女性であり、データベースを更新する必要があります。
不変のPOJOを使用している場合は、彼女を表すPersonオブジェクトをフェッチしてから、変更していないすべてのプロパティと新しい姓を渡す新しいPersonオブジェクトを作成し、新しい姓を保存します。
Java Beanの場合は、setLastName()を実行して保存できます。
それは「可変オブジェクトを使用しない」ではなく「可変性を最小化する」ことです。状況によっては、変更可能なオブジェクトの方がうまく機能します。オブジェクトを変更可能にすることがプログラムに適しているかどうかを判断するのは、実際にはあなたの仕事です。常に「不変オブジェクトを使用する必要がある」と言う必要はありません。代わりに、自分自身を傷つけ始める前に、不変にすることができるクラスの数を確認してください。
他の回答を要約すると私は思います:
get(id): Client
とsave(MutableClient)
は不要で、MutableClientはクライアントの子孫です。中間点(作成、プロパティの設定、不変にする)があった場合、フレームワークはより不変のアプローチを奨励するでしょう。
とにかく、私は不変オブジェクトを「読み取り専用Java Beans」」と考えることをお勧めします。
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;
}
}
正直に言うと、不変オブジェクトがそれほど普及することはないと思います。
私には利点はありますが、HibernateやSpringのようなフレームワークは現在非常に流行しており(そしてそれには正当な理由もあります)、それらはBeanで本当に最もよく機能します。
だから不変性が悪いとは思いませんが、それは確かに現在のフレームワークとの統合オプションを制限するでしょう。
[〜#〜] edit [〜#〜]コメント回答を少し明確にするように求められます。
不変性が非常に有用であり、実際に使用されている問題領域があります。しかし、現在のデフォルトは変更可能であるように思われます。これは、ほとんどの場合予想されるものであり、明確な利点がある場合にのみ不変です。
また、Springで引数付きのコンストラクタを使用することは確かに可能ですが、これはレガシーコードやサードパーティのコードを美しい真新しいSpringコードで使用する方法として意図されているようです。少なくともそれは私がドキュメントから拾ったものです。