【问题标题】:How to set the instance to null inside class?如何在类内将实例设置为空?
【发布时间】:2014-01-22 12:45:34
【问题描述】:

我想在我的班级中创建一个release() 方法。 调用release() 后,如何将该实例设置为null

我的意思是:

ABC abc = new ABC();
abc.release();
if(abc == null) Log.d("That's what I want");

然后我想检查abc 是否为null。 我该怎么做?

【问题讨论】:

  • abc = null; 否则我听不懂。
  • abc = null; 怎么样?
  • 这和池化有关系吗?
  • 我猜你是 NullPointerException 的粉丝......

标签: java null garbage-collection


【解决方案1】:

您不必从每个实例内部执行此操作。如果您删除了对该对象的引用(所有个引用),那么它将在下次垃圾收集器执行他的轮次时自动删除。

简单地做

ABC abc = new ABC(); // Create new instance and reference it with variable abc
abc = null; // remove the reference from abc; the instance is now floating around in space

您可以尝试使用System.gc() 显式调用垃圾收集器。最后我记得读到这只是表明您想要 GC 而不是实际的力量,但文档只是说它“运行垃圾收集器”。

【讨论】:

    【解决方案2】:

    很遗憾没那么容易。 您想要这样的版本以防止进一步使用。分配 null 会给 API 客户端带来负担/善意。你希望它在代码中。也许间接地为:

    class ABC {
        void release() { ... }
        void generateOutputOnce() {
            ...; release();
        }
    }
    

    所以对真正的 ABC 对象使用委托:

    class ABC { // Maybe extends OriginalABC
         OriginalABC abc;
         ABC() {
             abc = new OriginalABC();
         }
         public void release() {
             abc = null;
         }
         public void generateOutputOnce() {
             checkRelease();
             abc.generateOutputOnce();
         }
         public void anyFunc() {
             checkRelease();
             abc.anyFunc();
         }
         private void checkRelease() {
             if (abc == null) throw new IllegalStateException("Already released");
         }
    }
    

    ABC 有一个界面会有所帮助; IDE 可以为委托生成存根。

    【讨论】:

      【解决方案3】:

      你不能那样做。对 ABC 类的引用存在于类本身之外(在调用者内部),因此 ABC 的实例无法修改引用。

      您必须在 ABC 中实现某种状态,就像数据库连接对象所做的那样。当您关闭数据库连接时,您仍然拥有对连接对象的引用,但该对象处于“关闭”状态,您不能再使用它(除非您先重新打开连接)。

      【讨论】:

        【解决方案4】:

        这在一定程度上取决于您何时考虑将引用归零。

        如果您有一个对象链 A->B->C,那么一旦 A 不可访问,A、B 和 C 都将有资格进行垃圾回收(假设没有其他内容涉及 B 或 C)。例如,没有必要也从来没有必要将引用 A->B 或 B->C 显式设置为 null。

        除此之外,大多数时候问题并没有真正出现,因为实际上您正在处理集合中的对象。您通常应该始终考虑通过调用适当的 remove() 方法从列表、地图等中删除对象。

        过去有一些建议设置对 null 的引用的情况特别是在长范围内,在该范围内停止使用内存密集型对象。例如:

        {
          BigObject obj = ...
          doSomethingWith(obj);
          obj = null;             <-- explicitly set to null
          doSomethingElse();
        }
        

        这里的基本原理是,因为 obj 仍在作用域内,所以如果没有显式地将引用置空,它直到 doSomethingElse() 方法完成后才会变为可垃圾回收。这就是现代 JVM 可能不再适用的建议:事实证明,JIT 编译器可以计算出在什么时候不再使用给定的本地对象引用。

        【讨论】:

          【解决方案5】:

          你不能。

          对对象的引用在 Java 中是按值传递的。你不能有一个方法改变调用对象的引用指向的地方。

          但是您可以做的是向 ABC 类添加一个public boolean isReleased() 方法,并将if(abc == null) 替换为if (abc.isReleased())

          任何在对象被释放后不再工作的方法在调用release() 后被调用时应该抛出一个自定义异常。这比当所有对对象的引用都是nulled 时得到的NullPointerException 可调试性好得多。

          【讨论】:

            【解决方案6】:

            此时 abc 可以是null。因为this = null; 不是一个有效的声明。

            你必须明确地使为空。

            【讨论】:

              【解决方案7】:

              变量abc 是一个单向引用。您可以根据需要对对象进行尽可能多的引用。对象无法*知道指向它的引用。

              您可以执行与您的请求类似的操作的唯一方法是,如果您要“取消”的对象具有对另一个对象的引用,该对象持有对该对象(以取消)本身的引用。

              现在您可以将这个对对象本身的引用设置为null。但这不会影响任何其他引用,因此该对象仍可能被使用且不符合垃圾回收条件。

              正如你所见,这个循环引用并没有揭示对象的职责和依赖关系。一般来说,应该避免循环依赖;应该首选树状结构。因此,release 方法不应由对象本身触发。相反,对象应该改变它的状态,可能是invalidend of life 状态,并通知其他感兴趣的对象(例如通过事件监听器或总线或消息系统)。持有引用的对象必须做出反应并将引用设置为null

              • 使用“正常”语言特征和模式

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2011-10-12
                • 2018-11-13
                • 2012-06-21
                • 1970-01-01
                • 2011-10-09
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多