【问题标题】:Why is it possible to use a Closed object outside of its try-with-resources scope?为什么可以在 try-with-resources 范围之外使用 Closed 对象?
【发布时间】:2016-01-05 03:12:31
【问题描述】:

I've read 在 try-with-resources 块中初始化的资源仅在该块期间的范围内。

如果是这样,那么这段代码似乎是如何解决这个问题的?

public class Main {
    public static void main(String[] args) throws Exception {
        final Main main = new Main();

        try {
            final char[] buffer = new char[10];
            StringReader stringReader = main.testStream();
            System.out.println(stringReader.read(buffer, 0, 10));
        } catch (IOException e) {
            System.out.println("expected IOException caught here"); 
        }

        try {
            HttpResponse response = main.tryResponse();
            response.getEntity();
            System.out.println("should not reach this line if response is out of scope");
        } catch (Exception e) {
            System.out.println("why no IOException here?");
        }
    }

    StringReader tryStream() throws IOException {
        try (StringReader reader = new StringReader("string")) {
            return reader;
        }
    }

    HttpResponse tryResponse() throws IOException {
        CloseableHttpClient client = HttpClientBuilder.create().build();
        HttpGet request = new HttpGet("http://www.google.com");
        try (CloseableHttpResponse response = client.execute(request)) {
            return response;
        }
    }
}

在这种情况下,Java 的最佳实践是什么?

【问题讨论】:

  • 这段代码应该 . . .不行。真的吗? stackoverflow.com/questions/22947755/…
  • 嗯,你会得到一个封闭的Closeable 回来。这与您认为会发生的情况不同吗?
  • @RealSkeptic 是的,是的。对于InputStream,访问关闭的流会引发异常。 Closeable对象有没有其他关闭后可以使用的例子?

标签: java httpclient java-7 try-with-resources


【解决方案1】:

作用域是一个编译时间概念,它控制源代码中名称的使用位置。来自JLS

声明的范围是程序所在的区域 声明所声明的实体可以使用 简单的名称,只要它是可见的(§6.4.1)。

换句话说,它不适用于对象(这是一个运行时概念),仅适用于引用它们的变量(和其他命名元素)。

对于您的示例(假设没有return),如果您尝试在try 块之外使用变量response,它将无法编译:

try (CloseableHttpResponse response = client.execute(request)) {    
} 
System.out.println(response); // nope, compilation error

return 语句计算给定的表达式(在这种情况下为变量),解析一个值(对 CloseableHttpResponse 对象的引用),复制该值,然后返回它,从中弹出当前方法堆栈帧堆栈并将执行返回到调用方法。

使用您的try-with-resources 语句,实际的return 操作前面有一个finally 块,该块在response 变量引用的对象上调用close()。据推测,这会使对象处于某种不可用状态。您可能会遇到运行时异常,具体取决于您使用它的方式(即在接收return 值的方法中)。

【讨论】:

  • 我明白了,所以术语是错误的,但更一般地说,问题的答案是:除了根据@987654335 关闭对象之外,没有关于关闭对象的状态或行为的规范@合约?
  • @jordanpg 没错。 Closeable 只是一个接口。 try-with-resources 只是一个调用closefancy try-catch-finally(这只是一个方法)。有Closeable 实现,其close 方法是无操作的,例如ByteArrayInputStream
  • @jordanpg 基本上,您应该遵循您使用的类型的 javadoc(或者如果文档的其余部分不好,则执行实现)来了解会发生什么。
猜你喜欢
  • 2013-09-12
  • 2015-11-26
  • 1970-01-01
  • 2015-01-19
  • 2018-02-07
  • 2014-10-19
  • 2017-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多