为什么我需要调用close()或shutdown()方法?

5

我之前学过C++,现在想用Java作为编程语言。我已经研究了关于Java的"析构函数"、finalize()方法和close()shutdown()方法的很多资料,但是我还是不太明白应该如何使用(当然下面提供更多信息)。

具体问题是:为什么需要调用close()shutdown()方法呢?我正在使用一个处理智能卡读卡器的类,但是我发现在文件管理中也需要调用close()方法,这两种情况是否相同?

难道调用close()方法的意思就是释放内存吗(就像C++一样)?换句话说,我必须负责删除或销毁对象......难道GC就不能做这个吗?

对于我正在尝试使用的智能卡读卡器类,可能实现finalize()方法是一个选项,这样在不再使用时,可以释放内存(最有可能是本地代码)和/或释放GC可能不知道如何处理的硬件资源。

那么对于文件管理类呢?那些非常常用和维护,为什么还需要close()方法呢?我理解存在的目的是为了解锁文件,但为什么我还要记得关掉它?一旦对象不再使用,自动释放文件,至少在最常见的情况下。

最后,将需要关闭或关闭的类包装在实现finalize()方法的类中并在那里调用close()shutdown()方法是否是一个适当的解决方案?

我发现finalize()方法并不是很流行,所以我想问这个问题应该如何解决。

谢谢!

Juan

PS:我看到的:

Java有析构函数吗?

为什么会实现finalize()?

http://www.codeguru.com/java/tij/tij0051.shtml

简单解释Java中的close()方法

我在使用File.getName()方法时需要关闭文件吗?


在Java 7中,可以使用try-with-resources语句来自动处理资源的正确关闭。 - Louis Wasserman
4个回答

3
大多数类都会在其finalize方法中清理其外部资源,但这与C++的析构函数不同-析构函数在对象不再使用时立即调用,但是直到垃圾回收器对对象进行垃圾回收后才会调用finalizer,并且您不知道这将在何时发生(如果您没有一个内存密集型程序,则可能永远不会发生)。因此,假设您正在分配一堆每个都分配数据库连接的对象(是的,您应该使用连接池,但这是一个假设);您使用每个对象,然后将其引用设置为null,以便可以在没有关闭其数据库连接的情况下进行垃圾回收,现在您的数据库会崩溃,因为它打开了太多连接。您可以调用System.gc,希望这将清除连接,但这仅是向垃圾回收器建议执行收集的建议,并且您的垃圾数据库连接的终结器可能不足以完全清理连接。

长话短说,您需要调用closeshutdown,因为您不知道对象的终结器是否会运行,也不知道它们清理外部资源的能力有多好。

顺便说一句,您应该使用try-catch-finally块来确保调用closeshutdown - 将这些方法放在finally块中。或者,如果您使用Java7,则使用try-with-resources。


2
我曾在一家公司工作,他们会在对象终结器中清理数据库连接等内容,但终结器也会将此记录为警告,例如:if(!connection.isClosed) { connection.close(); log.warn("在终结器中关闭连接,这是不好的事情"); } - Zim-Zam O'Pootertoot
@Zim-ZamO'Pootertoot 哈哈,怎么样!因为好答案给你点个赞。 - informatik01

2
Java垃圾回收器会为您完成工作,但在某些情况下(如套接字或数据库连接),您需要调用close方法(例如关闭与数据库的连接或文件处理程序等)。
有些人会调用连接的close()方法,然后将其设置为null,例如:
conn.close();
conn = null;

然后他们朝它的头部开枪,以确保它已经死亡。

1

Java的垃圾回收机制会自动释放不再被引用的内存。

但是它不会自动释放其他资源。因此,您需要显式地释放其他资源的方法。

好的,具体问题是为什么我需要调用.close或.shutdown方法?

为了释放不被自动处理的资源。

我理解存在的目的是为了解锁文件,但为什么我必须记得关闭它呢?

如果使用Java 7的带资源的try语句,则不必这样做。

最后,将需要关闭或关闭的类包装在实现finalize方法的类中并在那里调用close或shutdown方法是否是适当的解决方法?

不是的。您不能依赖于在对象不再被引用后不久或根本不会调用finalize()方法。


1
许多类都存在于封装外部实体的服务。在许多情况下,类的有用性将取决于其要求外部实体代表其采取行动,可能会损害该实体的其他潜在用户。一个类如果要求外部实体代表其采取行动直到另行通知,则承担了在不需要其服务时通知外部实体的责任。
调用close()将告诉对象其服务不再需要;(不再需要的)对象可以将消息传递给代表其采取行动的实体,告知他们也不需要提供服务。这种通知可能允许那些实体将其服务提供给其他潜在用户。
垃圾收集是基于系统知道何时需要内存的假设运行的,只有在系统需要释放内存时才清除垃圾并没有任何实际好处。这种哲学对于大多数使用close的东西并不起作用。在许多情况下,持有资源的代码将无法知道是否有其他人想要使用它。因此,代码通常应该尽量仅保留他们实际使用的资源的时间。一旦代码完成了对资源的使用,它就应该释放它,以便使其可供其他可能需要它的人使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接