ほとんどの不変のPOJOは次のように書かれています:
public class MyObject {
private final String foo;
private final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public int getBar() {
return bar;
}
}
しかし、私は次のようにそれらを書く傾向があります。
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
参照は最終的なものなので、オブジェクトは不変のままです。これにより、より少ないコードを記述でき、より短い(5文字ずつ:getおよび())アクセスが許可されます。
私が見ることができる唯一の欠点は、getFoo()何かおかしなことをするために将来の実装を変更したい場合、できないということです。しかし現実的には、オブジェクトは不変であるため、これは決して起こりません。インスタンス化中に検証し、インスタンス化中に不変の防御コピーを作成し(ImmutableListたとえばGuavaを参照)、オブジェクトfooまたはbarオブジェクトをget呼び出しの準備ができます。
欠けている欠点はありますか?
編集
私が見逃している別の欠点は、getまたはisで始まるメソッドのリフレクションを使用するシリアル化ライブラリであると思いますが、それはかなり恐ろしい習慣です...
String、int、またはMyObject。最初のバージョンでfinalはbar = 7;、たとえば、クラス内のコンストラクター以外のメソッドがを試行しないようにするだけです。2番目のバージョンでfinalは、消費者が以下を実行できないようにする必要がありますMyObject x = new MyObject("hi", 5); x.bar = 7;。
Objectなものなので、まだ不変であることに注意してください。」は誤解を招きます-そのように見えるのfinal Objectは、不変であると思われますが、そうではありません。誤解して申し訳ありません。
myObj.getFoo().setFrob(...)。
final変数をオブジェクト不変にしません。通常final、コールバックがそれらのフィールドにアクセスできるように、コールバックを作成する前にフィールドを定義するデザインを使用します。もちろん、メソッドを含むすべてのメソッドを呼び出すことができsetXます。