2012-09-20 3 views
14

私は、Javaのバージョンが7より小さいと、Joda TimeオブジェクトはJavaの組み込み関数よりも信頼性が高いと読んでいます。 1つの理由は、Jodaオブジェクトは不変であるという理由が挙げられます。なぜこれは有益なのでしょうか? Joda DateTimeオブジェクトの年、時間、およびタイムゾーンを変更したい場合は、3つのコピーを作成する必要があります。なぜJodaオブジェクトは不変ですか?

+1

逆に、DateTimeオブジェクトが不変でない場合、Javaに 'const'がないと仮定すると、サードパーティのAPIにパラメータとして渡すたびに、そのオブジェクトを複製すると仮定されます。 –

答えて

18

ジョーダDateTimeオブジェクトの年、時間、およびタイムゾーンを変更する場合は、3つのコピーを作成する必要があります。

はい、または、新しいオブジェクトを作成し、古いオブジェクトから好きなすべてのフィールドを使用することもできます。

これは徹底的に良いことです。変化しないオブジェクトに頼っていたいと思うからです。 Instantは不変であるので、大丈夫です

private static final Instant EARLIEST_ALLOWED_ARTICLE = ...; 

private Instant creationTimestamp; 

public Article(Instant creationTimestamp, ...) { 
    if (creationTimestamp.isBefore(EARLIEST_ALLOWED_ARTICLE)) { 
     throw new IllegalArgumetnException(...); 
    } 
    this.creationTimestamp = creationTimestamp; 
    ... 
} 

:この擬似コードを考えてみましょう。変更可能な場合は、その時点で防御的なコピーを作成していない限り、コンストラクタの検証は意味がありません。

私の経験では、参照を渡して、値が実際に既存のオブジェクトを変更したいと思う以上に変化しないようにするため、不変性によりバグが少なくなります。どんな妥当性検査も役に立たず、コピーが少なくなります。

基本的には、コードを受け入れるか保存するか、または他のコードに戻ることはできません。 あなたのコードだけがあなたのオブジェクトの状態を変えることができるとき、時間が経つにつれて起こることを簡単に解決することができます。 インターフェース(例えばReadableInstant)にあなただけのプログラムは、あなたがそれらの保証を取得しない場合 - それは可変不変型の両方を持っているので、

ジョダ時間は実際には多少失敗します。それで、Noda Timeでは、すべてのタイプを真に不変にしました。

お困りですか?Stringは変更可能ですか?そうでない場合、2つのシナリオの間に本当の違いがあるかどうかを考えてみてください。

+0

これは優れた点です。しかし、日付は本当に何か特別なものです、 "プリミティブ"(数字と文字列)は不変ですか?なぜあなたは*すべてのクラスを変更可能にしてはいけないのか、すべての*セッター*が*値を変更する前にコピーを作成していないのかという疑問が浮かび上がってきます。あなたが書いたすべてのセッターに 'クローン'または 'コピー'と書くのは本当に意味がありません。これは基本的な問題を暗示します。 – caw

+1

@caw:そうです、日付は本当に*特別なものだと言います。変更可能な型を持つことは間違いありませんが、実現可能な場合は一般的には不変型を優先します。しかし、低レベルの "プリミティブ"型がすべて可変であれば、*可変性または不変性の* choice *は実装するのがはるかに難しくなります...不変のクラスは常に*すべてをクローンする必要があります*。 Urgh。 –

+0

ありがとう!日付と他の一般的なオブジェクト(例えば、コレクション、 'カレンダー'、ビジネスロジックからのオブジェクト)の間に大きな違いはまだありません。とにかく、後で変更することができない(したがってパブリックセッターを持たないかもしれない)オブジェクトの間に*実質的な違いがあり、コンストラクタ/セッターで受け取ったデータをクローンするだけですJoshua Blochが "Effective Java"で推奨しているものです)と、*変更しようとするオブジェクトはすべてのセッターで自分自身をコピーする必要があります。 – caw

3

最も単純な答えは、オブジェクトを作成すると、に変更できないことがわかります。つまり、予期しない方法でデータが変更されるような状況に陥ることはありません(おそらく、コードの他の部分や別のスレッドではおそらく)。

これにより、オブジェクトの動作がより予測可能で信頼性が高くなります。

1

多くの理由があるかもしれませんが、1つの良い点はハッシングです。不変オブジェクトは、ハッシュコードと "等価"セマンティクスが変更されないため、ハッシュデータ構造(HashSet、HashMapsのキーなど)で使用できます。可変オブジェクトはハッシュコードや等価性を変更する可能性があるため、可変オブジェクトはハッシュには適していません。

Jodaの日付を不変にすることで、データ構造のハッシュ処理に使用できるようになりました。

1

私はそれがこのによるものだと仮定します:

あなたはjava.util.Dateオブジェクトを持っている想像し、それを複数のクラスで使用されています。私は1つのクラスで開発をしています。それから私は将来を予測する必要があると判断しますが、新しいDateオブジェクトを作成するのではなく、私がすでに持っているもの、つまり特定の時点を表すと考えるものを取り上げ、それに3時間を追加します。さて、あなたのコードは実行時に深刻な問題に遭遇するかもしれません。これは、あなたがその状態を変更することはできないので、不変のオブジェクトを使って避けることができます。他の誰かのためにそれを混乱させることはできません。

1

残念ながら、finalが使用されていないため、DateTimeの実装は不変ではありません[1]。

https://github.com/JodaOrg/joda-time/blob/master/src/main/java/org/joda/time/DateTime.java

[1]用語 "不変" は一般に "スレッドセーフ不変" を意味すると理解されます。

+0

私は理解していません.. DateTimeは 'final'クラスです。' BaseDateTime'のフィールドを意味するなら 'はい'であり、リフレクションを使って変更できますが、 'String'もそうではありません不変。 – Premraj

+0

ファイナルは誰もリフレクションで変更を止めません。 – Tobb

関連する問題