2017-02-20 14 views
3

Immutable objectsライブラリを使用して不変クラスを作成すると、どのように変更可能なメンバー(たとえばj.u.Date)を扱うことができますか?変更不可能なアイテム

注:これはない JavaのDateクラスについて、いくつかのコードを生成します不変オブジェクト Javaライブラリには全く関係しています!

例:

@Value.Immutable 
public interface MyImmutableClass { 
    Date creationDateTime(); 
} 

ゲッターをオーバーライドする方法は、それはコピーを返すように、ありますか?それはコピーを返すように

public Date creationDateTime() { 
    return new Date(creationDateTime.getTime()); 
} 
+2

[不変の日付クラス](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html)を使用することもできます。そうであれば、必ずゲッターを持ってくださいコピーを返す。 '新しい日付を返します(creationDateTime。getTime()); ' – khelwood

+0

私はjava8の機能を使うことはできませんし、Dateだけでなく他のクラスにも影響する可能性があります。 – TmTron

+0

参照@stackoverflow.com/questions/7082553/java-util-date-clone-or-copy-to-not-expose-internal-reference – khelwood

答えて

1

私は変更可能なオブジェクトを処理するためのクリーンな方法はcustom encoding annotationを使用することを学んだImmutables issue trackerの私の質問から。

java.util.Dateクラスのアノテーションを作成するために、少しオープンソースのプロジェクトtmtron-immutables encodingを作成しました。これは、カスタムエンコーディングを作成したいすべての人にとっては良い出発点になるはずです。

は、その後、あなたが直接属性として(例えばjava.util.Date)あなたの可変クラスを使用することができますし、まだ(文字列、長い、などのように)不変の属性と同じ不変性の保証を得る

@Value.Immutable 
@DateEncodingEnabled 
public interface ValueObject { 
    Date creationDate(); 
} 

@DateEncodingEnabled注釈が作成されますDateオブジェクトの不変なlong値のみがImmutableValueObjectクラスに格納されていることを確認してください。

1

ゲッターをオーバーライドする方法は、ありますか?

public Date creationDateTime() { 
    return new Date(creationDateTime.getTime()); 
} 

(のようなkhelwoodは、上記のコメントで指摘):あなたはそこに書いたほとんどのよう

。あなたはクラス内creationDateTimeの偶発変異を避けたい場合は

しかし、ちょうどfinal longとしてミリ秒を格納考える:

private final creationDateTimeMillis; 

public Date creationDateTime() { 
    return new Date(creationDateTimeMillis); 
} 

をあなたはDate.setTime()を呼び出すことができるのに対しDateは、このように変異、finalであっても、内部状態では、creationDateTimeMillisを再割り当てすることはできません。

+0

まあ、私は何とかそれをコピーする必要があることを知っています:質問は "Immutables注釈プロセッサにこれを行う方法を教えてください"です。 – TmTron

1

あなたは、生成されたメソッドprotectedを作るだけクローニングgetterメソッドからフィールドを提供することができます:

@Value.Immutable 
public abstract class WrapMutable { 
    protected abstract Date timestamp(); 

    public Date getTimestamp() { 
     return new Date(timestamp().getTime()); 
    } 
} 

timestamp()方法のみに使用されている間、フィールドのすべての使用法は、そのコピーゲッターを通じて、その後でビルダーでセッターを定義します。

WrapMutable obj = ImmutableWrapMutable.builder().timestamp(new Date()).build(); 
System.out.println(obj.getTimestamp()); 
System.out.println(obj.timestamp()); // Error: timestamp() has protected access in WrapMutable 
+0

それは本当に不変ではありません。 'WrapMutable'のサブクラスを作成するだけで、' timestamp() 'を不正に呼び出すメソッドを追加できます。 'timestamp'プロパティは' long'のように不変のものを格納したり返す必要があります。 –

+0

@AndyTurner:[Immunables framework](http://immutables.github.io/)の文脈で質問を読んだことがあります。その目的は、悪質な開発者からの保護ではなく、テスト中に非常に役立ちますが、POJOインスタンスを提供することです。そのコレクションは初期化され、そのフィールドは設定され、そのオプションはnull以外です。フレームワークを使用すると、多くの定型文が削除され、必要な防御コーディングの量を減らすのに役立ちます。 – Henrik

関連する問題