首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >(何时)应该尝试-将AutoCloseable构造函数括起来?

(何时)应该尝试-将AutoCloseable构造函数括起来?
EN

Stack Overflow用户
提问于 2020-09-08 11:47:47
回答 4查看 313关注 0票数 3

Oracle Java文档,用于新的“尝试-使用-资源”展示了AutoCloseable正在try(...)中构造的所有示例

代码语言:javascript
复制
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    ...
}

这似乎是安全的,因为即使构造函数(相对于后续事件)已经获得了必须释放的资源,如果我们遇到异常,它们也会被释放。

但是,正如https://www.baeldung.com/java-try-with-resources所指出的,从Java9开始,我们可以有效地使用在try(...)之前初始化的最终资源

代码语言:javascript
复制
FileOutputStream fos = new FileOutputStream("output.txt");
try (fos) { 
    // do stuff
}

在类似的Java-9之前,我看到:

代码语言:javascript
复制
CustomStreamLikeThing connection = new CustomStreamLikeThing("db_like_thing");
// ... do some stuff that may throw a RuntimeException
try (CustomStreamLikeThing connection2=connection) { 
    // do some more stuff
}

这似乎是合法的,但同时在某种程度上削弱了这一概念:如果CustomStreamLikeThing获得了可关闭的资源,它们可能不会被释放。

是否有关于AutoCloseable的构造函数何时应该包含在try(...)中的指导方针,或者这是否是一个趣味问题(例如“将所有我认为可能引发异常的东西都包含进来”)?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2020-09-08 12:39:01

是否有关于AutoCloseable的构造函数何时应该包含在try(...)中的指导方针,或者这是否是一个趣味问题(例如“将所有我认为可能引发异常的东西都包含进来”)?

编码的基本规则是:你是故意做任何事情的。这就要求您了解自己正在做什么,以及代码中的每一件“事情”都在做什么。

意思:如果你有一些东西需要“关闭”,那么常识就是:用资源来尝试。

但是,您是专门询问“对象创建”的微妙方面的。这应该进入try(),还是可以在此之前完成?!

要做到这一点:只要您的源代码在语义上做了正确的事情,就没有硬规则。因此,它可以归结为这两个方面:

  • 你与你的团队交谈,你同意你的“首选”风格,然后你的整个团队遵循这一点。换句话说:选择你喜欢的风格,然后坚持下去:保持一致!
  • 你看你的要求。您的try(fos)选项适用于java9。对于那些不需要修补旧产品的人来说,这很好。但是对于那些经常要把“相同的改变”贴在同一产品的不同版本上的人.这些人可能更喜欢可以合并到java8环境中的源代码。
票数 1
EN

Stack Overflow用户

发布于 2020-09-08 12:27:43

如果可能的话,您应该始终使用使用试用式资源。

当您分配资源时,您应该确保资源在完成时总是被释放。“始终”通常意味着您应该使用try-finally,这样在资源分配之后发生的任何错误都不会阻止资源被释放。

这意味着,如果您不使用具有资源的尝试,那么您需要使用try-finally,那么为什么我说总是使用具有资源的尝试呢?

因为调用close()也可能失败,而使用资源进行尝试时,添加了一个特性,称为抑制异常

如果您曾经对一个失败的close()调用的堆栈跟踪进行过诅咒,它已经取代了本应在“使用资源的尝试”块中抛出的异常,那么您就会知道这一点的重要性,所以您现在不知道到底是什么导致了这个问题。

抑制异常是一个通常被忽略的特性,但是当一个级联异常被close方法抛出时,它节省了很大的时间。仅就这一点而言,请始终使用“尝试与资源”。

副作用:与使用try-finally相比,使用资源的尝试代码更少,在处理资源时,您肯定应该使用这两种方法之一。

票数 2
EN

Stack Overflow用户

发布于 2020-09-08 12:02:57

当构造函数直接出现在try-with语句中时,如下所示:

代码语言:javascript
复制
try (MyCloseable c = new MyCloseable()) {
    // do stuff with c
} catch (IOException e) {
    // handle exception
}

然后,在以下任何一个抛出异常时都会调用catch块:

  • 构造函数
  • 试体
  • close()-method.

因此,当每个特殊情况都抛出一个IOException时,不可能有一个catch块。

然而,使用这样的代码,您可以更多地控制异常处理:

代码语言:javascript
复制
MyCloseable c;
try {
    c = new MyCloseable();
} catch (IOException e) {
    // handle constructor exception
}
try (c) {
    // do stuff with c
} catch (IOException e) {
    // handle exception from close() or try-body
}

但是,在上面的示例中,对于try-body和close方法,仍然有一个catch块,并且不建议这样做:

代码语言:javascript
复制
// initialize c like in the second example
try (c) {
   try {
       // do stuff with c
   } catch (IOException e) {
       // handle try-body exception
   }
} catch (IOException e) {
   // handle close() exception
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63793265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档