【问题标题】:Why do I need to call a close() or shutdown() method?为什么我需要调用 close() 或 shutdown() 方法?
【发布时间】:2013-04-10 20:10:41
【问题描述】:

我是 Java 新手,高中时有一些 C++ 背景。现在我正在尝试做点什么,我选择了 Java 作为编程语言。

我已经完成了我的功课,并且看了很多关于 Java 的“析构函数”、finalize() 方法和 close()shutdown() 方法。但我仍然认为我不知道这应该如何工作(当然下面有更多信息)

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

在我的特殊情况下,我正在使用一个我没有开发的处理智能卡读卡器的类,但我已经看到文件管理的情况,你必须调用 close( ) 方法,应该是类似的。

调用 close() 方法与在 C++ 中释放内存的想法不同(很糟糕)?意思是,我必须处理对象的删除或销毁......不是GC吗?

我尝试用于智能卡读卡器的类可能不是最好的,这可能是一个选项,这个类实现 finalize() 方法可能会更好,所以当不再使用并为 GC 做好准备,释放内存(很可能是本机代码)和/或释放 GC 可能不知道如何做的硬件资源。

但是文件管理类呢?这些都非常使用和维护,为什么仍然需要 close() 方法?我明白存在的目的,解锁文件,但为什么我要记得关闭它?一旦不再使用对象,然后自动解锁文件,至少在最常见的情况下是这样。

最后,用实现 finalize() 方法的类来包装需要关闭或关闭的类,并在那里我调用 close() 还是 shutdown() 方法?

我看到finalize()方法不是很流行,所以才问这个问题应该怎么解决。

提前致谢

胡安

PS:我所看到的:

Is there a destructor for Java?

Why would you ever implement finalize()?

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

explain the close() method in Java in Layman's terms

Do I need to close files I perform File.getName() on?

【问题讨论】:

  • 在 Java 7 中,try-with-resources 语句可用于为您正确处理自动关闭资源。

标签: java garbage-collection shutdown finalize


【解决方案1】:

存在许多类来封装外部实体的服务。在许多情况下,一个类的有用性将取决于它要求外部实体代表它做某事直到另行通知,这可能会损害该实体的其他潜在用户。要求外部实体代表其行事直至另行通知的类会自行承担在不再需要其服务时通知外部实体的责任。

调用close() 将告诉对象不再需要它的服务;因此,(不再需要的)对象可以将消息传递给代表它行事的实体,也不需要他们的服务。然后,此类通知可能会允许这些实体将其服务提供给其他潜在用户。

垃圾收集的运行假设系统知道何时需要内存,并且在系统可以使用可以释放的内存之前,清除垃圾并没有任何真正的好处。这种哲学不适用于大多数使用close 的东西。在许多情况下,拥有资源的代码无法知道其他人是否想要使用它。因此,代码通常应尝试仅在资源实际使用期间保留资源。一旦代码完成了资源,它应该释放它,以便其他任何可能需要它的人都可以使用它。

【讨论】:

    【解决方案2】:

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

    它不会释放其他资源。因此,您需要一个显式方法来释放其他资源。

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

    释放未自动释放的资源。

    我明白存在的目的,解锁文件,但为什么我要记得关闭它?

    如果您使用 Java 7 的 try-with-resources,则不必这样做。

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

    没有。在不再引用对象后,您不能依赖很快或根本不调用 finalize() 方法。

    【讨论】:

      【解决方案3】:

      大多数类将在其finalize 方法中清理其外部资源,但这与 C++ 的析构函数不同——一旦不再使用对象就会调用析构函数,但不会调用终结器直到一个对象被垃圾收集,你不知道什么时候会发生(如果你没有一个内存密集型程序,它可能永远不会发生)。因此,假设您正在分配一堆对象,每个对象都分配一个数据库连接(是的,您应该使用连接池,但这是一个假设);您使用每个对象,然后将其引用清空,以便可以在不先关闭其数据库连接的情况下对其进行垃圾收集,现在您的数据库将因打开太多连接而对您产生影响。您可以调用System.gc,希望这会清理连接,但这只是对垃圾收集器执行收集的建议,并且您的垃圾数据库连接的终结器可能不够聪明完全清理连接。

      长话短说,您需要调用 closeshutdown,因为您不知道对象的终结器是否/何时运行,并且您不知道它们在清理外部方面的能力如何资源。

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

      【讨论】:

      • 我在一家公司工作,该公司将在其对象终结器中清理数据库连接等,但终结器也会将此记录为警告,例如`if(!connection.isClosed) { connection.close(); log.warn("在终结器中关闭连接,这是一件坏事"); }
      • @Zim-ZamO'Pootertoot 哈哈,怎么样! +1 的好答案。
      【解决方案4】:

      java 垃圾收集器会为您完成工作,但在某些情况下(使用套接字或数据库连接)您需要调用 close 方法(例如关闭与数据库的连接或文件处理程序等) .

      有些人调用连接的 close() 方法,然后将其变为 null,例如:

      conn.close();
      conn = null;
      

      然后他们朝它的头部开枪,以表明它已经死了。

      【讨论】:

        猜你喜欢
        • 2015-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-29
        相关资源
        最近更新 更多