46

私が Java を扱ってから少なくとも 5 年は経ちますが、その頃は、クリーンアップが必要なオブジェクト (ソケット、DB ハンドルなど) を割り当てたいときはいつでも、finallyブロックを追加してクリーンアップ メソッドを呼び出すことを覚えていなければなりませんでした。そこの。

対照的に、C++ (または Perl などのオブジェクトの有効期間が決定論的である他の言語) では、クラスの実装者は、そのクラスのオブジェクトがスコープ外になるたびにクリーンアップを実行するデストラクタ関数を定義します。このアプローチの利点は、オブジェクトのユーザーがオブジェクトのクリーンアップを忘れないことです。例外がスローされた場合でも、デストラクタが自動的に呼び出されます。このアプローチは、RAII のかなりひどい名前 (「リソースの取得は初期化」) で行われます。

「RAII の方法」で物事を行うことで、リソースの割り当て解除が発生するかどうか、いつ発生するかを心配する必要がないという点で、多くの精神的オーバーヘッドを節約できたというのが私の経験です。私たちは中規模のプロジェクトに Java を使用することを検討していますが、最後に Java を調べてから言語に追加された多くの新機能の中に、ある種の決定論的破壊があるのではないかと考えています。(「JavaにはRAIIがない」という私の不満がこのスレッドで非難されたことを願っていますが、これまでのところ、グーグルで詳細を見つけることができませんでした。)

したがって、誰かがJavaでこれを行う方法についての入門資料を教えてくれれば、それは素晴らしいことです!

4

4 に答える 4

30

編集: 以下の回答は、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 に関するもので、かなり古いものですが、よく読む価値があります。

于 2009-01-25T08:54:05.933 に答える
10

ここで役立つパターンがあります。デストラクタベースのRAIIほど優れていませんが、リソースのクリーンアップをライブラリに移動できることを意味します(したがって、呼び出すことを忘れないでください)。

これはExecuteAroundと呼ばれ、前にここで説明しました

興味深いことに、Jon Skeetがそのスレッドでチャイムを鳴らしているのがわかりますが、彼はここでそれについて言及していませんでした。

ところで、私はブライアン・ハリー(ジョンのコメントをもう一度参照)が彼がした電子メールを書くのに長けたことを嬉しく思います-そしてそれは明らかにプロセスに入った多くの考えを反映していました-そして私は私たちがやったことをうれしく思いますC#でそれを「使用」する-私は彼のすべての結論に同意しません。特に、使用できるのであれば、「使用」せずにタイプをそのように動作するものとしてマークする方法がない理由がわかりません。もちろん、それは使用法を制限します-しかし「使用」もそうします-そしてほとんどの場合それはまさにあなたが望むものです。「使用」の問題は、クライアントコードがそれを使用することを覚えておく必要があることです。C ++スタイルのRAIIでは、このタイプのプロパティです。「使用する」、より正確にはDisposeイディオムでの間違いなく大きな問題は、それが

于 2009-02-14T13:18:26.703 に答える
2

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

サーバーで作業している場合は、Java EEをチェックアウトすることをお勧めします。RAII とは関係ありませんが、DB 接続などの高価なオブジェクトのライフサイクルを管理するための適切なシステムがあります。実際、Java EE 5 は、多くの問題領域で使用するのに非常に適しています。

于 2009-01-25T09:17:57.320 に答える
-1

私が取っているアプローチは、リソースの割り当てを処理する階層化された製品 (単純な静的メソッドの場合もあります) を使用することです。この種のリソース割り当てがプログラムを散らかすことは望ましくありません。

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

于 2009-01-25T10:30:09.703 に答える