2011-01-13 3 views
3

一般的に言えば、Javaで不変オブジェクトを使用するほど、私はもっと良いアイデアだと思っています。彼らは自動的にスレッドセーフでクローン作成やコンストラクタのコピーを心配する必要がないという利点をたくさん持っています。Javaの不変なキーワードは良いアイデアでしょうか?

これは私には「不変の」キーワードが間違っていると思いますか?明らかに、言語に別の予約語を追加することには欠点があり、主に上記の理由でそれが実際に起こるのではないかと疑いますが、それを無視して、多くの欠点は実際には分かりません。

現在、オブジェクトは不変であることを確認するために注意を払わなければならず、コンポーネントオブジェクトを主張するdadgy javadocのコメントでも、事実上すべてを破壊することはできません。また、ストリングのような基本的なオブジェクトでさえも、攻撃を反射するのは容易に想像できるので、真に不変ではないという議論もあります。

不変のキーワードがあれば、コンパイラは再帰的にチェックし、クラスのすべてのインスタンスが不変であることを保証することができます。これは現在実行できません。特に並行性がますます高くなるにつれて、私は個人的にこの効果にキーワードを追加することをお勧めします。しかし、私はこれが悪い考えになる欠落している欠点や実装の詳細はありますか?

+1

これは不要で、使用には極端に制限されています。 – Falmarri

+3

@Falmarri逆に、私は不変のオブジェクトがかなり多く使われていると思います。 –

+0

C++は 'const'でジョブを実行します。個人的には、もしJavaが似たようなキーワードを持っていれば、私は非常に満足しています。なぜなら、(例えば) 'Collections.unmodifiableCollection'のようなもので回り込むことなく、特定のインスタンスを不変としてマークすることができるからです。 'const'と' mutable'(遅延読み込みを可能にする)の組み合わせは、良いものと思われます。 –

答えて

4

通常、ステートフルオブジェクトよりも不変オブジェクトが好ましく、it's currently fairly difficult to make an immutable object in Javaよりも不変オブジェクトが優先されるべきです。実際、多くのオブジェクト指向言語は、不変オブジェクトのサポートが貧弱ですが、ほとんどの関数型言語はF#、Haskell、Clojureなど、それらを当然としています。 Javaへの不変のキーワードは、コードを作ることができる追加

...書くことが

  • 簡単。 finalprivateを迷惑しないようにしてください。誤ってクラスを変更可能にするメソッドを追加しないでください。手動でクラスfinalsubclasses can add mutable state)をマークすることはできません。
  • 読みやすい。クラスが英語で不変であると言う必要はありませんが、コード自体でそれを言うことができます。不変のキーワードは、自己文書化コードに向かう良いステップです。
  • 高速(理論上)。コンパイラがコードを知っているほど、最適化が多くなります。このキーワードがなければ、new ImmutableFoo(1, 2, 3)を呼び出すたびに、クラスが変更できないことをコンパイラーが証明できない限り、新しいオブジェクトを作成する必要があります。 ImmutableFooimmutableというキーワードが設定されている場合は、のすべてのコールでと同じオブジェクトが返されます。私はかなり確信していますnew常にこのポイントを無効にする新しいオブジェクトを作成するが、コンパイラとの効果的な通信はまだ良いことです。

Scala's case classes are similar to an immutable keyword.C# 5でも不変のキーワードが考慮されていました。

+0

不変クラスをお持ちの場合、なぜセッター関数を記述しますか? – Falmarri

1

私は不変の大きなファンです、私の意見では、絶対に。 OOプログラミングにおける不変性の利点は無数にあり、単なる関数型プログラミング言語の領域であってはなりません。

4

すべてのフィールドを最終的にするとともに、クラス参照もまた不変であることを検証することは不可能になる他の状況があります。

  • 最終クラスにレイジーロードフィールドも含まれている場合はどうなりますか? 不変および遅延のようなフィールドをマーキングするためのさらなるサポートが必要です。

  • chars []の配列を使ってjava.lang.Stringを見てみると、どのようにしてコンパイラが本当に不変であるかを本当に知ることができましたか?誰もが文字列を知っていますが、別の同様のクラスは配列を更新するメソッドを非常に簡単に含めることができます。さらなるサポートでは、フィールドが設定された後、他の命令が配列に「書き込む」ことができないことを検証する必要があります。これまではこれは非常に複雑な問題になりました。

最終的には、そのようなキーワードがうまくいけば助けになるかもしれませんが、それでもプログラムはそれほど優れているとは限りません。優れたコーダーによる優れたデザインは、より良い結果をもたらします。プラットフォームがいくつかの落とし穴を制限していても、ダムコーダーはやっかいなことを書くことができます。

+0

そこに良いポイント - 私は遅延ロードフィールドを考えていないと私はそれが簡単な問題ではないことに同意します。私はそれらの障害があまりにも多くの障壁になるはずがないと思っています。 (私は何かを正しく理解していない限り)プログラムをより良くするという意味では、自動的にクラップコードを改善するのではなく、良いコーダーに簡単な仕事。それ以外の不変のデザインを広く開いたままにする、現在の小さなものを見逃すことは非常に簡単です。そのようなキーワードが取り組むことを望む問題です。 – berry120

+0

私たちが座ってそれについて考えた場合、問題の複雑さはより多くのエッジケースで爆発し、より多くのエッジケースが導入されることは確かです。 –

+0

本当に有効な点ではありません。真に不変な配列の欠如はすでに大きな問題です。そのため、constがStringの問題を解決するのに役立ちます。明示的な同期を禁止する*、遅延ロードされたフィールドはすでに定義されているため、オブジェクトはスレッドセーフではないため、とにかく不変のラベルを付けることはできません。 –

1

オブジェクト指向のフレームワーク(Java、.netなど)には、可変配列、不変配列、可変配列参照、不変配列参照、および読み取り専用配列参照(読み込み専用参照は、可変配列または不変配列のいずれかを指すことができるが、いずれの場合も書込みが可能ではない)。不変の配列型がなければ、不変であることが証明できる方法で多くの効率的な型を構築するのは難しいです。

関連する問題