2013-07-02 2 views
5

私はAutoCloseableを実装するクラスを持っており、Java 7の新しいtry-with-resources構造で使用することを意図しています。しかし、クラスのユーザーがリソースを試して使用することを保証する方法を理解できません。これが起こらなければ、私のクラスはそれ自体を閉じることができず、悪いことが起こります。これを強制するために、言語構成やその他の方法がありますか?私がtry-with-resourcesブロックに入っているかどうかを検出することができても、そうでなければ例外をスローすることができます(コンパイル時の構成が望ましいかもしれませんが)。リソースの試行を強制するJava 7

ありがとうございます!

+0

try-with-resourcesを使用して自動的にではなく、クラスを手動で 'close'する方法を教えてください。 'close'と呼ばれる' finalize'メソッドを作成して問題を解決するでしょうか? – Jeffrey

+0

残念ながら、 'finalize'は呼び出される保証はありません。 GCはそれを呼び出さないことを決定するかもしれない。 – joshlf

+0

実際、「ファイナライズ」の信頼性がないのはおそらくリソースの試行が導入された理由だと思います。 – joshlf

答えて

3

残念ながら、ユーザーの愚かさからあなた自身を守る方法はありません。

finalizeメソッドを実装してcloseを呼び出すことができます。このようにすれば、少なくともそのオブジェクトがガベージコレクトされたときにリソースがクローズされていることを確認することができます。

プロジェクトの使用方法に制限を設けることができる場合は、アスペクト指向プログラミングを使用していくつかのポリシーを適用できますが、実際にJavaを使用していない可能性があります。賢明な資源が範囲内で使用してdiscartedできる場合

+1

Object.finalize()の使用は、Javaではお勧めできません。 –

+0

あなたが何をしているのかわからないと*他の選択肢はありません;) – Joni

+2

@DavidHofmann:あなたは何か誤解していると思います。 GCによって呼び出されるファイナライズに頼っているのはおそらく(そして理由があるのでは)避けていますが、実際には* finalizeメソッドを実装することは、場合によってはリソースリークを防ぐ唯一のオプションです。 – jarnbjo

-1

いいえ、方法はありません、あなたが開いたファイルやデータベース接続を維持する場合、同じ悪い事が起こるだろうとあなたはそれらを閉じないでください...

1つのメソッド呼び出しのうち、apiが呼び出されるたびに開くか閉じることができます。そうでない場合は、正しく動作を文書化してください。

あなたのクラスはシャットダウンフックを登録することもできるので、jvmがダウンしているときに少なくともリソースを閉じることができますが、これはとにかくライブラリの悪い習慣とみなされます。

+1

あなたは間違っています。最後の可能性として、リソースの漏洩を防止するために、それぞれのラッパー・インスタンスをファイナライズするときに、ファイルとネットワークまたはデータベース接続の両方が閉じられます。独自の目的のために同じ実装パターンを使用しないことは、正当な理由ではありません。 – jarnbjo

+0

説明のために@jarnbjoに感謝します。私が心に留めていたのは、あなたがそれらを閉じずにリソースを開いていれば、漏れがあるということです。とにかく、漏れをすぐに後で見るほうがいいと思います。閉じられていないオブジェクトへの参照を何らかの形で保持している場合、finalizeメソッドは呼び出されません。 GCに依存する場合、プログラムを実行するramとgcのチューニングの量に応じて、非決定論的な動作をする可能性があります –

1

リソース管理に本当に関心がある場合は、コールバック・イディオムを使用するのが最も安全な方法です。

:あなたは早期終了をサポートする場合

public interface Callback<T> { 
    void handle(T item); 
} 

public class SuperVitalVault { 
    public void all(Callback<Precious> callback) { 
    try (...) { 
     for (Precious i : ...) { 
     callback.handle(i); 
     } 
    } 
    } 
} 

あなたはbooleanを返すようにCallback.handle(T)を変更することができます:あなたは、エンドユーザーがコレクション内の項目を処理することを可能にするコレクションが、APIを公開していません。

try (...) { 
     for (Precious i : ...) { 
     if (callback.handle(i)) break; 
     } 
    } 

あなたは離れて独自のコールバックインタフェースを定義するから滞在したい場合は、グアバのFunction<T, Boolean>Predicate<T>を使用しますが、それはグアバによって確立されたセマンティクスに違反することに注意することができます

Functionのインスタンスは、一般的には、副作用がなく、明示的にトランスペアレントであることが期待されます。つまり、a.equals(b)は、function.apply(a).equals(function.apply b))。

プレディケートのインスタンスは、通常、副作用がなく、同等に一致すると予想されます。

関連する問題