はじめに
・try-with-resources文を使う場合と使わない場合の記述例を示します。
・try-with-resources文を理解するために有効なウェブサイトへのリンクを提供します。
・try-with-resources文はJavaSE7以降で使用可能です。
・try-with-resources文が利用できるクラスは、AutoCloseableインタフェースおよびそのサブインタフェースであるCloseableインタフェースの実装クラスに限られます。
try-with-resources文の記述例
try-with-resources文を使わない場合
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TryWithResources {
public static void main(String[] args) {
String inFilePath = "D:\\A.txt";
String outFilePath = "D:\\C.txt";
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(inFilePath);
out = new FileOutputStream(outFilePath);
int c;
// データをコピーする
while ((c = in.read()) != -1) {
out.write(c);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
ポイント
1.finally句がなくてもコンパイルエラーにはならないので、リソース開放漏れの危険性がある。
2.try句とfinally句の両方で同じリソースを指し示すことが必要なので、変数はtry-catch-finallyの外側で宣言する。
3.finally句のcloseメソッド呼出でIOExceptionの可能性があるため、try-catchのネストが必要。
try-with-resources文を使う場合
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TryWithResources {
public static void main(String[] args) {
String inFilePath = "D:\\A.txt";
String outFilePath = "D:\\C.txt";
try (FileInputStream in = new FileInputStream(inFilePath);
FileOutputStream out = new FileOutputStream(outFilePath)) {
int c;
// データをコピーする
while ((c = in.read()) != -1) {
out.write(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ポイント
1.基本的にリソースは自動開放。1
2.変数のスコープはtry句に限られる。
3.close時の例外は基本的には考慮不要。
参考サイト
Oracle Java SE Documentation try-with-resources文
TASK NOTES 【Java】try-with-resources構文について
try-catch-finally、try-with-resources、そして発生した例外たち
ちなみに
FileInputStreamなどのクラスはfinalizeメソッドの中でcloseを呼出しているため、リソース開放漏れのバグには気づきにくい(起こりにくい)のです。ただし、開放をGCに任せるのは非効率だしお作法としてよろしくないので、try-with-resourcesを利用しましょう。
package java.io;
import java.nio.channels.FileChannel;
import sun.nio.ch.FileChannelImpl;
public
class FileInputStream extends InputStream
{
===========================省略===========================
/**
* Closes this file input stream and releases any system resources
* associated with the stream.
*
* <p> If this stream has an associated channel then the channel is closed
* as well.
*
* @exception IOException if an I/O error occurs.
*
* @revised 1.4
* @spec JSR-51
*/
public void close() throws IOException {
synchronized (closeLock) {
if (closed) {
return;
}
closed = true;
}
if (channel != null) {
channel.close();
}
fd.closeAll(new Closeable() {
public void close() throws IOException {
close0();
}
});
}
===========================省略===========================
/**
* Ensures that the <code>close</code> method of this file input stream is
* called when there are no more references to it.
*
* @exception IOException if an I/O error occurs.
* @see java.io.FileInputStream#close()
*/
protected void finalize() throws IOException {
if ((fd != null) && (fd != FileDescriptor.in)) {
/* if fd is shared, the references in FileDescriptor
* will ensure that finalizer is only called when
* safe to do so. All references using the fd have
* become unreachable. We can call close()
*/
close();
}
}
}