【问题标题】:Is there C++ destructor equivalent in Java? [duplicate]Java中是否有等效的C++析构函数? [复制]
【发布时间】:2011-09-28 15:57:38
【问题描述】:

最简单的设计如下:

class Session {
  Timer t = new Timer();
  // ...
};

每当分配Session 时,我都会在其中启动一个计时器;计时器将在 10-20 分钟后到期。现在,假设如果Session 在计时器到期之前被销毁;那么这是我必须停止计时器的情况。我不知道是否有任何最后一个方法在 Session 被销毁时总是调用。

在 Java 中是否有某种等效的 C++ 析构函数,它可以帮助我在 Session 被销毁时 cancel() 计时器? (无需等待 GC)

编辑:请不要为 C++ 重新标记。我想要类似的东西。 Session 是一个电话会话,当所有连接到它的用户都断开连接时,它就会被破坏。现在,没有最后调用的Session方法,也没有任何异常。

【问题讨论】:

    标签: java destructor


    【解决方案1】:

    不,Java 中没有内置这样的东西。最接近的是编写一个终结器,但不能保证它会运行。

    Session 是如何被销毁的?如果有一个方法被调用,一定要把代码放在那里。

    如何创建会话?如果您在 try/catch 块中执行此操作,则可以在 finally 块中清理所有内容。

    我会编写一个 close() 方法来处理它并在 finally 块中调用它。

    【讨论】:

    • try...finally 是确保调用整理(“析构”)代码的方法。
    【解决方案2】:

    与 C++ 不同,您无法控制 Java 中的对象释放 - 也就是说,GC 在它认为合适的时候收集对象,只是保证它不会收集任何可以通过在给定时间范围内的任何引用到达的对象.

    Object.finalize(),它充当进行清理的最后机会挂钩,但运行时不保证它会被调用。

    我会重新考虑设计并尝试提出一种更明确的方式来清理您的计时器。

    【讨论】:

      【解决方案3】:

      在 Java 中,变量不像在 C++ 中那样直接表示对象——Java 中的变量是对对象的引用。所以对象不能超出范围——只有引用对象的变量才能超出范围。

      您可以重写 finalize(),它是 Object 类中的一个方法,当垃圾收集器即将永久丢弃一个对象时会调用该方法,但这与析构函数并不完全相同。请参阅 Object 类中 finalize() 方法的 API 文档。

      【讨论】:

        【解决方案4】:

        首先,finalize相当于析构函数。不要尝试将其用作一个;它行不通。 Java 没有为此内置任何内容,但在某些圈子中,有使用void dispose() 的约定;你写的是ptr.dispose(),而不是delete ptr;。 (当然,内存稍后会被回收。)在这种情况下,最好也定义finalize,如果在调用dispose 之前回收了对象,则会产生某种内部错误。

        【讨论】:

          【解决方案5】:

          大多数情况下,您可以构造问题,因此不需要析构函数。

          为每个 Session 创建一个 Timer 是比较重的。您最好将延迟任务提交给 ScheduledExecutorService。通过使其重量轻,就没有必要取消它。 (实际上 cancel() 并没有删除它,它被标记为不运行)

          在这种情况下,为了简单起见,您可以使用单例 ScheduledExecutorService。

          class Session {
              private static final ScheduledExecutorService timer = 
                                              Executors.newSingleThreadScheduledExecutor();
              private Future<Void> timeoutFuture = null;
          
              // call every time you want the timeout to start from now.
              public void resetTimer() {
                  if(timeoutFuture != null) timeoutFuture.cancel(false);
                  timeoutFuture = timer.schedule(new Callable<Void>() {
                      public Void call() {
                          sessionTimedOut();
                          return null;
                      }
                  }, TIMEOUT_SECONDS, TimeUnit.SECONDS);
              }
          
              void sessionTimedOut() {
                  // what to do when the session times out.
              }
          }
          

          这里是昂贵的组件,ScheduledExecutorService 被创建一次,并在应用程序的生命周期中存在。 Future 在 Session 被清理时被丢弃(并且任务已经过期)

          【讨论】:

          • +1 有趣,ScheduledExecutorService 是什么。你能详细说明一下你的答案吗?
          • 我添加了一个例子。
          【解决方案6】:

          在java中没有这样的方法。顶级Object 中定义的finalize() 方法可以在垃圾收集器销毁对象时调用,但这不是您可以依赖的行为。

          您可以做的最好的事情就是将对象设置为 null(删除引用),这将使它准备好进行垃圾回收。

          【讨论】:

            【解决方案7】:

            您可以使用 CDI(上下文依赖注入) - 例如 Weld,或者在某些 JEE 服务器(TomEE、JBoss 等)上运行程序。下面是一个使用数据库的示例。

            在您的类上使用适当的 @...Scoped(ApplicationScoped、SessionScoped 等)注释,如您所愿,例如:

            @ApplicationScoped
            public class MyDatabaseFactory implements Serializable {}
            

            @PostConstruct 注释的方法在构造函数中做你想做的事:

            @PostConstruct
            private void initializeObjectsOrConnections() {
              // ...
            }
            

            使用 @Inject 注释将您的对象注入到其他地方(如果您愿意的话):

            public class MyApplication {
            
              @Inject
              MyDatabaseFactory databaseFactory;
            
              // ...
            }
            

            清理、销毁对象并断开与数据库的连接 - 您想在使用 MyDatabaseFactory 类的 @PreDestroy 注释的方法中从 C++ 的析构函数中执行的操作,例如:

            @PreDestroy
            private void destroyObjectsOrCloseConnections() {
              // ...
            }
            

            它使用起来非常简单,我们在 Java 中拥有相当于 C++ 的析构函数。

            【讨论】:

              猜你喜欢
              • 2011-04-07
              • 2015-09-10
              • 2018-07-07
              • 1970-01-01
              • 2013-12-26
              • 2017-12-23
              • 2019-09-29
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多