1

私は定期的に次のスタイルのリソース クリーンアップを目にします。

InputStream in = null;
try {
    in = new FileInputStream(file);
    // ...
} finally {
    if (in != null) {
        in.close();
    }
}

私は常に次のスタイルを使用しています。

final InputStream in = new FileInputStream(file);
try {
    // ...
} finally {
    in.close();
}

しかし、私は何かが欠けていますか?私が見ていない前者に利点はありますか?

4

6 に答える 6

1

1 つではなく 2 つの入れ子になった try/catch ブロックを避けるためだと思います。

InputStream in = null;
try {
    in = new FileInputStream(file);
    // ...
} catch(IOException ioe) {
    // handle exception.
} finally {
    IOUtils.closeQuietly(in);
}

2 番目のケースは不完全です。

try {
    final InputStream in = new FileInputStream(file);
    try {
        // ...
    } finally {
        in.close();
    }
} catch(IOException e) {
    // handle exception
}

複数のファイルがある場合、これは非常に面倒になる可能性があります。

于 2012-08-30T14:58:39.330 に答える
0

1つではなく、2つのファイルを開く必要があるとします。あなたはします

final InputStream in = new FileInputStream(file1);
final OutputStream out = new FileOutputStream(file2);
try {
    // ...
} finally {
    out.close();
    in.close();
}

out失敗した場合は例外が発生し、tryブロック外であるため、ブロックin内で閉じられませんfinally

他の方法では:

InputStream in = null;
OutputStream out = null;
try {
    in = new FileInputStream(file1);
    out = new FileOutputStream(file2);
    // ...
} finally {
    if (out != null) out.close();
    if (in != null) in.close();
}

out開くことができない場合は、finallyブロックに移動して両方のストリームを閉じます。in開くことができない場合は、finallyブロックに移動し、解放するだけですin-なぜならout==null

編集

aetheriaが述べたように、close()Javaで例外がスローされるため、そのコードは機能しません。try各リソースリリースを独自の-catchブロックに配置することで簡単に修正できます。

InputStream  in  = null;
OutputStream out = null;
try {
    in = new FileInputStream(file1);
    out = new FileOutputStream(file2);
    // ...
} finally {
    try{ out.close(); }catch(Exception e){}
    try{ in.close();  }catch(Exception e){}
}

nullチェックを破棄しました-inまたはがnullの場合、無視されるoutaがスローされます。NullPointerExceptionそして、私closeが例外を無視する理由は、廃棄メソッドがそもそも例外をスローしてはならないからです。終了例外の処理が必要な場合は、ブロック後にいつでもストリームを再度閉じることができます。そうすれば、閉じることができるfinallyすべてのストリームがすでに閉じられており(したがって、心配する必要はありません)、よりエレガントに例外を処理できます。close

さて、aetheriaは、次のようになるリソースごとに個別のtry-ブロックを配置することも提案しました。finally

final InputStream in = new FileInputStream(file1);
try {
    final OutputStream out = new FileOutputStream(file2);
    try {
        // ...
    } finally {
        out.close();
    }
} finally {
    in.close();
}

これは機能しますが、リソースが2つしかない場合でも、割り当てとリリースコードが分割され、追跡が困難になるため、エレガントさが大幅に低下します(少なくとも私の意見では)。

于 2012-08-30T15:17:46.860 に答える
0

InputStreamこれは非常に単純な例であり、同じブロークで作成しているため、問題が発生しない場合があります。しかし、他の障害InputStreamが原因で が閉じられException orている場合、その場合、コードは失敗しInputStreamます 。

于 2012-08-30T15:05:48.773 に答える
0

最初の例で、inを定義する前に、try ブロックから抜け出す別のコードがあるとします。定義されていない状態で finally に到達すると、それを閉じようとすると NullPointerException が発生します。そのため、そのようなエラーを回避するためにチェックを行う必要があります。

于 2012-08-30T14:56:53.277 に答える
0

変数が割り当てられていない可能性があるため、ここでのnullチェックが必要です。InputStreamこの場合、呼び出し時に閉じようとすると NullPointerException がスローされます。

in.close();

try/catch ブロックの外側の 2 番目のブロック:

final InputStream in = new FileInputStream(file);
try {
    // ...
} finally {
    in.close();
}

ブロックに入る前に他の例外に簡単に遭遇する可能性があり、ブロックInputStreamが閉じられることはありません。

于 2012-08-30T14:57:36.800 に答える
0

FileInputStreamのコンストラクターがをスローできるため、2番目のものはコンパイルされません。したがって、もちろんメソッド自体がスローしない限りFileNotFoundException、追加のブロックが必要になります。try-catch

もう 1 つの一般的なイディオムは、ブロック全体にチェックcloseQuietly()を書き込む必要がないようにメソッドを記述することです。これが Apache Common の機能です。if (is != null)finallyIOUtils

public static void closeQuietly(InputStream input) {
  try {
    if (input != null) {
      input.close();
    }
  } catch (IOException ioe) {
    // ignore
  }
}

また、Java 7以降では、以下を使用できることに注意してください。

try (InputStream is = new FileInputStream(file)) {
} catch (final FileNotFoundException | IOException ex) { 
}
于 2012-08-30T15:01:27.663 に答える