Java 为什么可以在try with resources范围之外使用封闭对象?

Java 为什么可以在try with resources范围之外使用封闭对象?,java,httpclient,java-7,try-with-resources,Java,Httpclient,Java 7,Try With Resources,在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];

在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的最佳实践是什么?

范围是一个编译时的概念,它控制着源代码中名称的使用位置。从

声明的范围是程序的区域,其中 可以使用 简单名称,只要是可见的(§6.4.1)

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

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

try (CloseableHttpResponse response = client.execute(request)) {    
} 
System.out.println(response); // nope, compilation error
return
语句对给定的表达式(本例中为变量)求值,解析值(对
CloseableHttpResponse
对象的引用),复制该值,然后返回,从堆栈中弹出当前方法堆栈帧,并将执行返回给调用方法


使用
try With resources
语句,实际的
return
操作前面有一个
finally
块,该块调用
response
变量引用的对象上的
close()
。这可能会使对象处于某种不可用的状态。您可能会得到运行时异常,这取决于您随后如何使用它(即在接收
返回值的方法中)。

此代码应该。不工作。真的吗?那么,您将得到一个closed
Closeable
返回。“这和你认为会发生的事情不同吗?”真怀疑论者是的,的确如此。对于
InputStream
,访问关闭的流会引发异常。是否还有其他可以在关闭后使用的
可关闭的
对象的示例?我明白了,所以术语是错误的,但更一般地说,这个问题的答案是:除了根据
Closeable
contract?@jordanpg关闭对象之外,没有关于关闭对象的状态或行为的规范<代码>可关闭
只是一个界面
try with resources
只是一个调用
close
(这只是一个方法)的函数。例如,
ByteArrayInputStream
Closeable
实现,它们的
close
方法是不可操作的。@jordanpg基本上,您应该遵从您正在使用的类型的javadoc(或者如果文档的其余部分不好的话,则是该实现),以了解期望得到什么。