5

この質問は 2 つの部分に分かれています。

InputStream i1 = new InputStream()とはどう違いnew InputStream()ますか?
そして、
それらを閉じるためだけにすべてのローカル変数を作成する価値はありますか?

変数を保持し、変数を使用し続け、優れたプログラマーのように入力ストリームを閉じることさえできる最初の簡単な答えを私は知っています。参照を失った秒ですが、より簡潔に見えます。2つのメモリの違いはありますか?速度差(破壊時)はどうですか?

次に、私の考えに拍車をかけた例に進みます。まず、捨てることを気にせず「new Object()」を使います。

 public void getLongStrings() throws IOException {
        try {
            foo = FileCopyUtils.copyToString(new InputStreamReader(aBook.getInputStream()));
            bar = FileCopyUtils.copyToString(new InputStreamReader(aNovel.getInputStream()));
        }
        catch (IOException ioe) {
            //do something appropriate here;
        }
    }

次に、より詳細な方法について説明します

public void getLongStrings() throws IOException {
        InputStream i1 = null;
        InputStream i2 = null;
        InputStreamReader isr1 = null;
        InputStreamReader isr2 = null;
        try {
            i1 = aBook.getInputStream();
            i2 = aNovel.getInputStream();
            isr1 = new InputStreamReader(i1);
            isr2 = new InputStreamReader(i2);
            foo = FileCopyUtils.copyToString(isr1);
            bar = FileCopyUtils.copyToString(isr2);
        }
        catch (IOException ioe) {
            //do something appropriate here
        } finally {
            if (i1 != null) i1.close();
            if (i2 != null) i2.close();
            if (isr1 != null) isr1.close();
            if (isr2 != null) isr2.close();
        }
    }

1回目と2回目どっちがいい?一方が他方より速いですか?きれいに見えなくても、すべてのストリームを閉じるのは賢明ですか?

洞察(または編集)をありがとう。

4

3 に答える 3

7

参照を失った秒ですが、より簡潔に見えます。

はい、より簡潔です。あなたはそのオブジェクトに対してより少ないことをしています - 重要なのは、あなたがすべきことをしていないということです。ショートカットを使用すると生成されるコードが少なくなることがよくありますが、ファイル ハンドルを開いたままにしてファイナライザーを閉じる処理を保留すると、確実に再現するのが難しい例外が発生することがわかります。

2つのメモリの違いはありますか?

たぶん、しかしそれは関係ありません。ここで重要なリソースはメモリではなく、ファイル ハンドルです。

速度差(破壊時)はどうですか?

繰り返しますが、無関係である可能性があります。正しさははるかに重要です。

(現在の 2 番目のコードはまだ完全に信頼できるわけではないことに注意してください。初期のclose()呼び出しの 1 つが例外をスローした場合、残りは閉じません。)

Java 7 を使用している場合は、try-with-resources ステートメントを確認する必要があります。これにより、これらすべてがより簡単になります。

編集: JB Nizet の回答に記載されているように、使用しているコードは基になるストリームを既に閉じている可能性がありFileCopyUtilsます。それは何であるかによって異なります。春のクラスなら大丈夫です。それ以外の場合は、そうではない可能性があります。ドキュメントを読む必要があります。ただし、一般的な原則は上記のとおりです。何かがストリームを閉じることを確認する必要があります。この場合、物事を明示的に閉じる必要がないという理由だけで、それは一般的な場合に当てはまると思い込まないでください。

GuavaInputSupplierとインターフェースはここで便利であることに注意してください。OutputSupplierこれにより、入力/出力がまだ開かれていないことを知ってサプライヤーを渡すことができます...つまり、他のコードが開く/コピー/閉じる(または何でも)を実行できることを意味しますが必要です)そしてそれをすべて処理します...コード内で閉じられる可能性のあるオブジェクトを使用することはありません。

于 2013-05-22T22:18:23.290 に答える
4

これが Spring の FileCopyUtils であると仮定すると、その javadocは次のように述べています。

すべてのコピー メソッドは 4096 バイトのブロック サイズを使用し、完了したら影響を受けるすべてのストリームを閉じます

(私のものを強調)

したがって、この場合、最初のアプローチは完全に問題ありません。Spring は Reader のクローズを処理し、Reader をクローズすると、ラップされたストリームがクローズされます。

そうでない場合は、できれば Java 7 のtry with resourcesを使用して、リーダーを閉じる必要があります。

2 番目の例では、ストリームを閉じますが、その必要はありません。リーダーを閉じると、自動的に閉じます。また、最初のリーダーを閉じることができず、IOException をスローした場合、2 番目のリーダーは正しく閉じられないことに注意してください。try with resourcesを使用するもう 1 つの理由は、すべてを閉じることが保証されていることです。

于 2013-05-22T22:22:23.383 に答える
1

提供されたストリームを閉じFileCopyUtils.copyToString() ないと仮定すると、2 番目のアプローチの方が優れています。

close()ストリームに関連付けられているすべてのリソースを解放するために呼び出す必要があります。したがって、コードの美しさやパフォーマンスの問題ではなく、正確さの問題です。

2 番目の方法にはバグがあり、いずれかのclose呼び出しで例外がスローされると、残りのすべてのclose()呼び出しが呼び出されません。

于 2013-05-22T22:18:33.700 に答える