jdk7のリソース管理

先日リリースされたjdk7。
あまり大きな変更点は無いのかな?
気になるのはStringのswitch、AutoCloseale、ジェネリクスコンストラクタの簡略化くらいか。


早速AutoCloseableを試してみた。

import java.io.*;

public class Main {

	public static void main(String[] args) {
		try {
			try (FileInputStream fis = new TestStream1("Main.java")
				; InputStreamReader isr = new InputStreamReader(fis)
				; BufferedReader br = new BufferedReader(isr)) {
				System.out.println(br.readLine());
			}
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	public static class TestStream1 extends FileInputStream {

		public TestStream1(String fileName) throws IOException {
			super(fileName);
		}

		public void close() throws IOException {
			new Exception().printStackTrace();
			System.out.println();
			super.close();
		}

	}

}

で、こうなる。

import java.io.*;
java.lang.Exception
        at Main$TestStream1.close(Main.java:25)
        at sun.nio.cs.StreamDecoder.implClose(StreamDecoder.java:377)
        at sun.nio.cs.StreamDecoder.close(StreamDecoder.java:192)
        at java.io.InputStreamReader.close(InputStreamReader.java:199)
        at java.io.BufferedReader.close(BufferedReader.java:517)
        at Main.main(Main.java:11)

java.lang.Exception
        at Main$TestStream1.close(Main.java:25)
        at Main.main(Main.java:11)

こうすると、

import java.io.*;

public class Main {

	public static void main(String[] args) {
		try {
			try (FileInputStream fis = new TestStream1("Main.java")
				; InputStreamReader isr = new InputStreamReader(fis)
				; BufferedReader br = new BufferedReader(isr)) {
				System.out.println(br.readLine());
			}
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	public static class TestStream1 extends FileInputStream {

		public TestStream1(String fileName) throws IOException {
			super(fileName);
		}

		public void close() throws IOException {
			new Exception().printStackTrace();
			System.out.println();
			if (true) {
				throw new IllegalArgumentException("");
			}
			super.close();
		}

	}

}

こうなる。

import java.io.*;
java.lang.Exception
        at Main$TestStream1.close(Main.java:25)
        at sun.nio.cs.StreamDecoder.implClose(StreamDecoder.java:377)
        at sun.nio.cs.StreamDecoder.close(StreamDecoder.java:192)
        at java.io.InputStreamReader.close(InputStreamReader.java:199)
        at java.io.BufferedReader.close(BufferedReader.java:517)
        at Main.main(Main.java:11)

java.lang.Exception
        at Main$TestStream1.close(Main.java:25)
        at sun.nio.cs.StreamDecoder.implClose(StreamDecoder.java:377)
        at sun.nio.cs.StreamDecoder.close(StreamDecoder.java:192)
        at java.io.InputStreamReader.close(InputStreamReader.java:199)
        at Main.main(Main.java:11)

java.lang.Exception
        at Main$TestStream1.close(Main.java:25)
        at Main.main(Main.java:11)

java.lang.IllegalArgumentException:
        at Main$TestStream1.close(Main.java:28)
        at sun.nio.cs.StreamDecoder.implClose(StreamDecoder.java:377)
        at sun.nio.cs.StreamDecoder.close(StreamDecoder.java:192)
        at java.io.InputStreamReader.close(InputStreamReader.java:199)
        at java.io.BufferedReader.close(BufferedReader.java:517)
        at Main.main(Main.java:11)
        Suppressed: java.lang.IllegalArgumentException:
                at Main$TestStream1.close(Main.java:28)
                at sun.nio.cs.StreamDecoder.implClose(StreamDecoder.java:377)
                at sun.nio.cs.StreamDecoder.close(StreamDecoder.java:192)
                at java.io.InputStreamReader.close(InputStreamReader.java:199)
                ... 1 more
        Suppressed: java.lang.IllegalArgumentException:
                at Main$TestStream1.close(Main.java:28)
                ... 1 more

なるほど。
closeの中でエラーが出てもすべてのcloseが呼ばれる、と。
すべてのエラーはThrowable#getSuppressed()で取得できる、と。
最初に出たExceptionが直接コードから見えるものになる、と。