web-dev-qa-db-ja.com

Java Scannerを閉じないことは安全ですか?

リーダーを使用するメソッドがあり、スキャナーを使用してリーダーで操作したい場合:

Scanner scanner = new Scanner(reader);
while(scanner.hasNext()) {
    //blah blah blah
}

scannerを閉じないのは安全ですか?ドキュメントには、「このスキャナーを閉じる」と書かれており、基礎となる読み取り可能ファイルを閉じることについて説明しています。読み取り可能ファイルを閉じたくないので、代わりに呼び出し側に準備ができたらreaderを閉じたいとします。ここでscannerを閉じない方が安全ですか?

32
Anthony

それはあなたが何に対して安全になりたいかによります。

  • 基になるストリームが閉じていることを確認しようとしている場合は、どちらのアプローチでも問題ありません。

  • Scannerをクローズとしてマークする場合(オブジェクトに対する後続のすべての操作がすぐに失敗するように)、Scanner.close()を呼び出す必要があります。

これは一般的な原則です。つまり、メモリ内のバッファリングを何らかの方法で行うさまざまな種類のストリームにも適用されます。

23
Stephen C

私はすでにソースコードを開いているので:-) ...

close()メソッドは、基になるReadableCloseableインターフェイスも実装しているかどうかを確認し、実装している場合はそれを閉じます。あなたの状況では、これは後で閉じられるため、これは問題ではないと言っています。

ただし、close()メソッドは、Scanner(および基礎となるReadable)が閉じていることを示す内部フラグも設定します。パブリックメソッドの多くは、最初にScannerが閉じられているかどうかを確認します。そのため、ここでの危険性は、基礎となるReadableが閉じられている可能性がありますが、Scannerをさらに呼び出しても、すぐにIllegalStateExceptionがスローされず、代わりに他の彼らが進む方法。

問題のScannerインスタンスへのハンドルが他にないことを確認でき、それ以上のメソッドを呼び出そうとしない場合は、大丈夫です。

close()メソッドもReadableへの参照をnullにするため、これが起こらない場合は、Scannerはすぐにガベージコレクションされません。 close()を呼び出しました。

可能であれば、Scanner.close()を呼び出します。

9
David

Scannerも閉じる必要があり、さらに作業を進めるために、基になるストリームを開いたままにしておく必要がありました。私がやったのは、BufferedInputStreamを拡張し、close()メソッドを空のボディでオーバーライドするクラスを作成することです。このクラスは、Scannerのコンストラクターに入力しました。これにより、ストリームを閉じずにscanner.close()を呼び出すことができます。ただし、元のBufferedInputStreamへの参照を保持する必要がありますが、それは明らかです。

1
Chris

まあ、Caller and Readerクラスがあれば。呼び出し元は、Readerの実装について知る必要はありません。読者の次の方法では:

while scanner has object
   read them ( one object per method's call) 
when objects are done
   close the reader. 

これは一種のイテレータパターンです。

0
StKiller