【问题标题】:Why is declaration required in Java's try-with-resource为什么 Java 的 try-with-resource 需要声明
【发布时间】:2017-10-29 15:11:56
【问题描述】:

Java7 的 try-with-resources 非常棒,但我无法理解为什么需要在 try 语句中包含资源声明。我的直觉说以下应该是可能的:

CloseableResource thing;
try (thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
    // do some interesting things
}
thing.collectSomeStats();

唉,这会导致语法错误(神秘地期待 ;)。将类型定义/声明移动到 try 语句中是可行的,这当然会将事物移动到相应的范围内。当我想从我的AutoClosable 获得更多而不是关闭时,我可以弄清楚如何解决这个问题,我对为什么编译器需要它感兴趣。

【问题讨论】:

标签: java try-catch


【解决方案1】:

Java 9 开始,您可以在块外声明和初始化 try-with-resources 内使用的变量。变量的唯一附加要求是它必须是effectively final
所以现在可以这样做了:

CloseableResource thing = methodThatCreatesAThingAndDoesSomeSideEffect();
try (thing) {
    // do some interesting things
}
thing.collectSomeStats();

希望对你有帮助。

【讨论】:

    【解决方案2】:

    你的版本没有明确定义应该关闭什么,例如

    CloseableResource thing;
    Parameter a;
    
    try (a = (thing = methodThatCreatesAThingAndDoesSomeSideEffect()).getParameter()) {
    

    如果你写了怎么办

    try (12) {
    

    还是什么?

    CloseableResource thing1 = methodThatCreatesAThingAndDoesSomeSideEffect();
    CloseableResource thing2 = methodThatCreatesAThingAndDoesSomeSideEffect();
    
    try(thing1) {
    }
    

    为什么只关闭thing1

    因此,当前的语法会强制您在打开关闭块的同时创建一个变量。

    ALSO2

    CloseableResource thing1 = methodThatCreatesAThingAndDoesSomeSideEffect();

    try(thing1) {
    }
    
    thing1.doSomethingOnClosedResource();
    

    因为thing1 仍然存在。

    【讨论】:

    • 你的第一点很好;离开声明打开了一个时髦表达的世界,确实可能在关闭什么方面产生很多歧义。第二个是简单的pebkac,Java试图避免太多恕我直言。但我想这只是个人喜好:)
    • 在第一个示例中,A 不可关闭,因此它不是真正的资源尝试,第二个示例,您只会打开事物 1,因此它只会关闭事物 1,不要发现问题
    • @Aviram,如果A 也是closeable 怎么办?
    • 所以你初始化了一个资源并将它绑定到thing和a,关闭a将关闭该资源
    • #1: 表达式可以被评估,它必须导致 AutoCloseable 的某些实例,这将被关闭:在你的情况下 a (和 @987654331 @,这是对同一事物的引用)。想想if (boolean expression),无论你在那个表达式中弄乱了多少布尔值,它都永远不清楚。 #2: 从语法上讲,AutoCloseable 表达式可以提供多个; 分隔符。 #3:没有人阻止我做try (CloseableResource alias = thing1) { ... },然后thing1在那个块之后仍然在范围内,所以这个防御是没用的。
    【解决方案3】:

    阅读 java 规范我得出了这个结论(虽然它没有暗示如此):

    它们让你声明变量并为其添加一个隐式 final 以确保你不能将变量重新绑定到其他东西。

    在这种情况下,将无法关闭资源,因为它不再绑定到变量。

    例如:

    CloseableResource thing;
    try (thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
        thing = null;
        // thing can't be closed now
    }
    

    我猜他们可以让你使用 final 如果它在外面,但它有点难看。


    解决方法: 如果你想访问声明的资源,你可以使用finally

    try (CloseableResource thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
        // do some interesting things
    } finally {
        thing.collectSomeStats();
    }
    

    记住最后thing已经关闭

    【讨论】:

    • 不是真正的 why 问题的答案,但仍然有效。
    • 是的,我注意到在我提交答案并开始阅读 java lang 规范后,看看他们是否解释了任何内容,但到目前为止没有任何解释
    • 我很高兴读到我可以访问 finally 块中的资源并尝试了它。但是我得到“无法将事物解析为变量”。因此,此解决方法不起作用
    猜你喜欢
    • 2015-11-26
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多