【问题标题】:Java, executing a method when object's scope endsJava,当对象的范围结束时执行一个方法
【发布时间】:2011-01-08 05:38:21
【问题描述】:

我有一个具有特定状态的对象。对象被传递,它的状态暂时改变。比如:

public void doSomething(MyObject obj) {
    obj.saveState();
    obj.changeState(...);
    obj.use();
    obj.loadState();
}

在 C++ 中,可以在构造和解构时使用对象的范围来运行一些代码,例如

NeatManager(MyObject obj) { obj.saveState(); }
~NeatManager() { obj.loadState(); }

然后这样称呼它

void doSomething(MyObject obj) {
    NeatManager mng(obj);
    obj.changeState();
    obj.use();
}

这简化了工作,因为保存/加载与NeatManager 对象的范围绑定。有可能在 Java 中做这样的事情吗?当对象超出其声明的范围时,有没有办法调用方法?我不是在谈论 finalize() 也不是“破坏”(垃圾收集),我对范围很感兴趣。

谢谢

【问题讨论】:

    标签: java object scope destructor


    【解决方案1】:

    不,没有这样的事情。最接近的可能是 try/finally 块:

    try
    {
        obj.changeState(...);
        obj.use();
    }
    finally
    {
        obj.loadState();
    }
    

    这确保即使在抛出异常或有早期的return 时也会调用loadState()

    【讨论】:

      【解决方案2】:

      不,没有那样的东西。你得到的最接近的是 try/finally。

      在 C# 中有 using 语句,它在末尾执行 Dispose 方法:

      using (Stream x = ...)
      {
      } // x.Dispose() is called here, in a finally block
      

      Java 7 有可能获得一些类似的东西,但我认为还没有什么是一成不变的。

      【讨论】:

      • 谢谢,在 Java7 中听到这个很有趣。
      【解决方案3】:

      Java 7try-with-resources,您可以扩展AutoCloseable 类来使用它。

      对于 Java 6,您可能希望查看相关问题:What is the best way to emulate try-with-resources in Java 6?

      【讨论】:

        【解决方案4】:

        另外请注意,不要试图使用 Object.finalize() 方法,该方法在对象被 GC 时运行,因为您无法控制何时收集对象。

        【讨论】:

        • 好的,谢谢。我读了一些关于 finalize() 的内容,但我发现情况并非如此。谢谢。
        【解决方案5】:

        简短回答:不。

        中等答案:这种情况下的最佳做法是使用try ... finally 块。

        更长的答案:C++ 也没有真正给你这个:C++ 析构函数在解除分配时运行。如果你未能释放一个对象并且对它的所有引用都超出了范围,则不会调用析构函数。

        顺便说一句,如果 Java 中的垃圾收集是引用计数,那么终结器将完全实现这种行为。

        【讨论】:

        • 事实上,C++ 确实支持 OP 所要求的内容。
        • 我不明白你为什么在长答案中这么说。我认为函数完成后所有对象都被破坏了,因为堆栈从所有分配的对象中释放出来。另外,我很确定这是一个很好的做法,正如我在 GOTW 上读到的那样,但我不确定,我会检查一下。编辑:不确定是 GotW、Exceptional C++ 还是更特殊的 C++:\
        • 是的,当引用它们的堆栈被释放时,将在堆栈分配的对象上调用 C++ 析构函数。但是,在堆分配的对象(即大多数程序上的绝大多数对象)上,析构函数只会在使用 delete 关键字的显式销毁时调用。
        • 在 C++ 中,像这样的本地对象往往是堆栈分配的。除非您想自己管理对象的生命周期,否则不要使用 new 关键字将某些内容放在堆上。堆栈分配的对象在对象超出范围时被破坏。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-06
        • 1970-01-01
        • 2019-10-13
        • 2016-11-24
        • 2014-02-12
        • 1970-01-01
        相关资源
        最近更新 更多