Edited at

try-with-resources文の基本

More than 1 year has passed since last update.


はじめに

・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を利用しましょう。


FileInputStream.java

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();
}
}
}