手法 JavaはRAII/確定的破壊をサポートしていますか?



unique_resource (4)

Javaで作業してから5年以上経っています。そのときは、クリーンアップが必要なオブジェクト(ソケット、DBハンドルなど)を割り当てるときはいつでも、 finallyブロックを追加してクリーンアップメソッドを呼び出す必要がありましたそこで。

対照的に、C ++(またはオブジェクトの存続期間が決定的な他の言語、例えばPerl)では、クラス実装者は、そのクラスのオブジェクトが範囲外になるたびにクリーンアップを実行するデストラクタ関数を定義します。 この方法の利点は、オブジェクトのユーザーがそのオブジェクトをクリーンアップするのを忘れることができないことです。たとえ例外がスローされたとしても、デストラクタは自動的に呼び出されます。 このアプローチは、RAIIのかなりひどい名前、「Resource Acquisition Is Initialisation」によって行われます。

「RAIIのやり方」をすることで、リソースの割り当てが解除されるかどうか、またリソースの割り当てが解除されるのを心配する必要がなくなり、精神的なオーバーヘッドが大幅に削減されたことは私の経験でした。 私たちは、中規模のプロジェクトにJavaを使用することを検討しています。最後に見たときから、言語に追加された多くの新機能の中に何らかの決定的な破壊があるのか​​疑問です。 (私はこのスレッドで "JavaにはRAIIがない"という私の苦情として期待していますが、これまで私はグーグルで詳細を見つけることができませんでした。)

だから、もし誰かがJavaでこれについてどうやって行くべきかについての入門的な資料を教えてくれればそれは素晴らしいだろう!


Answer #1

ここで役立つパターンがあります。 デストラクタベースのRAIIほど素晴らしいわけではありませんが、リソースのクリーンアップをライブラリに移すことができます(つまり、呼び出すことを忘れることはできません)。

これはExecute Aroundと呼ばれ、これまでここで議論されています

興味深いことに、Jon Skeetがそのスレッドでチメットを見るのが見えますが、ここでは言及していませんでした.Jonさんはいくつかのポイントを得る機会を逃しました!

ところで、Brian Harry(Jonのコメントを参照)は、彼がやった電子メールを書いていたことに喜んでいました。明らかに、プロセスに入った多くの考えが反映されています。 C#でそれを "使って"得る - 私は彼の結論すべてに同意しない。 特に私が使用することができれば、タイプを「使用する」ことなくそのように振る舞うものとしてマークする方法はありません。 もちろん、それは使用方法を制限しますが、「使用する」こともあります。そして、ほとんどの場合、あなたが望むものです。 "using"の問題は、クライアントコードがそれを覚えなければならないことです。 C ++スタイルのRAIIでは、このタイプのプロパティです。 Disposeイディオムを「使用する」、またはより正確にDisposeイディオムを使用することにより、おそらくオブジェクトが死から戻される可能性があるため、ほとんどの人が実現するよりも、はるかに複雑でエラーが発生しやすいという大きな問題があります。


Answer #2

いいえ。 スタックにオブジェクトを割り当てる機能はありません。 すべてのオブジェクトはヒープ上に割り当てられ、初期化されたブロックよりも長く存続する可能性があります。または、すべての強力なガベージコレクタのバラリに応じて、中間ブロックで収集されます。

サーバーで作業している場合は、 Java EEをチェックアウトすることができます。 それはRAIIとは関係ありませんが、DB接続のような高価なオブジェクトのライフサイクルを管理するためのまともなシステムを持っています。 Java EE 5は実際には多くの問題空間で作業するのにかなりいいです。


Answer #3

編集:以下の答えはJava 7が非常に流動的であった2009年の初めに書かれました。

Javaは依然として確定的な破壊を持っていませんが、C#のusingステートメントのような機能を得ました: try-with-resourcesステートメント

いいえ、Javaはその点で全く変更されていません。 try / finallyを使用する必要があります。

C#の "using"ステートメント(try / finallyよりも構文上の砂糖)をJavaに追加する議論がありましたが、それはJava 7の一部ではないと思います。 (ほとんどの言語の改良点はなくなっているようです。)

Javaと.NETでは、決定論的な破壊が実装されていない理由があることを理解する価値があります。これは、a)パフォーマンスに影響を与え、b)循環参照で失敗する参照カウントを含む傾向があります。 Brian Harryはこれについて詳細なメールを書きました。これは.NETに関するもので、8歳以上ですが、読んでみる価値があります。


Answer #4

私が取るアプローチは、リソース割り当てを担当するレイヤード製品(時には単純な静的メソッド)を使用することです。 あなたは、この種のリソース割り当てがあなたのプログラムを浪費することは望ましくありません。

これを行うライブラリはたくさんあります。 ほとんどの場合、心配する必要はありません。





raii