JDK的try-with-resources示例中的不良做法?

时间:2017-11-02 20:14:22

标签: java try-with-resources

我在Java的try-with-resources文档中找到了这个例子:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

如果BufferedReader的构造函数抛出异常,则FileReader所拥有的资源将不会被释放。所以这不是一个不好的做法,而不是:

static String readFirstLineFromFile(String path) throws IOException {
    try (FileReader fr = new FileReader(path);
         BufferedReader br = new BufferedReader(fr)) {
        return br.readLine();
    }
}

2 个答案:

答案 0 :(得分:1)

确实,只是试了一下:

public class MyFileReader extends FileReader {

    public MyFileReader(String fileName) throws FileNotFoundException {
        super(fileName);
    }

    @Override
    public void close() throws IOException {
        System.out.println("Closing MyFileReader");
        super.close();
    }

}

public class MyBufferedReader extends BufferedReader {

    public MyBufferedReader(Reader in) {
        super(in);
        throw new RuntimeException();
    }

    @Override
    public void close() throws IOException {
        System.out.println("Closing MyBufferedReader");
        super.close();
    }

}

public String test(String path) throws IOException {
    try (BufferedReader br = new MyBufferedReader(new MyFileReader(path))) {
        return br.readLine();
    }
}

MyFileReaderMyBufferedReader都没有关闭......好抓!

同时:

public String test(String path) throws IOException {
    try (FileReader fr = new MyFileReader(path); BufferedReader br = new MyBufferedReader(fr)) {
        return br.readLine();
    }
}

MyFileReader已关闭。

BufferedReader构造函数确实可以抛出异常,请参阅BufferedReader(Reader in, int sz) constructor(虽然不是来自BufferedReader(Reader in) constructor,但您链接的文档仍应警告此问题恕我直言。)

看起来你赢得了raise an issue:)

的权利

答案 1 :(得分:0)

不幸的是,你是对的。

以下示例显示了此行为 - Internal的实例永远不会关闭。

public class Test {
    public static void main(String[] args) {
        try (External external = new External(new Internal())) {
        }
    }
}

class External implements Closeable {
    private Internal internal;
    public External(Internal internal) {
        this.internal = internal;
        throw new RuntimeException("boom");
    }

    @Override
    public void close() {
        System.out.println("External.close()");
        internal.close();
    }
}

class Internal implements Closeable {
    @Override
    public void close() {
        System.out.println("Internal.close()");
    }
}