【问题标题】:Bad practice in JDK's try-with-resources example? [duplicate]JDK 的 try-with-resources 示例中的错误做法? [复制]
【发布时间】:2018-04-15 11:37:52
【问题描述】:

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

【问题讨论】:

  • 据我所知,BufferedReadet 的这个构造函数没有抛出任何异常。
  • @TobiasWeimer 第二个构造函数确实抛出了 IllegalArgumentException。
  • 我知道。但根据其文档,第一个没有:docs.oracle.com/javase/9/docs/api/java/io/…
  • 我的观点是,即使特定的构造函数没有抛出异常,我仍然不会将其用作教学示例,因为它忽略了与该主题相关的潜在问题。

标签: java try-with-resources


【解决方案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 的权利:)

【讨论】:

    【解决方案2】:

    很遗憾,你是对的。

    以下示例显示了这种行为 - 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()");
        }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-06
    • 2018-10-20
    • 2014-12-18
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-25
    相关资源
    最近更新 更多