【发布时间】:2020-12-09 15:16:57
【问题描述】:
假设我有一个类C,其中包含需要作为成员变量关闭的资源。
public class C {
private ClosableResource1 closableResource1;
private ClosableResource2 closableResource2;
.....
public C(){
closableResource1 = new ClosableResource1();
closableResource2 = new ClosableResource2();
.....
// some logic that can fail
}
close(){
closableResource1.close()
closableResource2.close()
.....
}
}
如果构造函数成功,我可以确定close() 最终会被某个实体管理器调用,并且所有资源都将被释放。
但是如何确保在构造函数失败时关闭资源?失败可能是因为我在构造函数中有额外的逻辑可以抛出异常,或者我得到了一些超出我控制的RuntimeException?
我想到的一些事情:
- 用
try-catch块包装构造函数主体。然后,假设我有很多可关闭的成员,我必须在catch块中有一个大的if语句,检查哪些资源已经在初始化并且只关闭它们。 - 将
ClosableResources 创建卸载到某个init()函数。然后,每次尝试使用该对象时,我都必须确保init()成功。
有什么优雅的解决方案吗?或者这是否比那个更具体?
【问题讨论】:
-
有理由不使用
try-with-resources吗?当在您的构造函数中使用时,这可能是一个可行的选择。可能更好的是定义init()函数并在对象构造之后显式调用它们,因为这样您就不会将资源管理绑定到对象创建。 -
我认为这样做根本不是一个好主意。传递您想要处理的资源,不要将资源管理与其使用混为一谈。
-
@daniu 当资源是特定于实现并且仅与将使用它们的类相关时传递资源是否仍然有意义?假设我有一些
FileReader类,它在后台管理一个 Mongo 数据库,所以每个FileReader实例自然应该可以访问一些 Mongo 客户端。为什么FileReader的用户甚至应该知道 Mongo,更不用说将客户端传递给它了? -
@Starless 您应该始终避免在构造函数中创建对象。在您实例化
C的地方,您可以尝试首先实例化您的可关闭资源,然后传递给C- 如果存在,则无需担心C的状态发生错误。 -
@Starless 您可以创建一个中间类来为您创建实例而无需打扰客户端,例如一个知道 MongoDB 并具有方法
createFilereader的“FileReaderService”,它将返回一个创建的阅读器使用适当的 Mongo 实例。然后客户端只需要知道服务就可以创建对象。
标签: oop