代码之家  ›  专栏  ›  技术社区  ›  sal

将Java对象设置为NULL不再有用吗?

  •  106
  • sal  · 技术社区  · 15 年前

    我浏览了几本旧书,找到了一本Peter Hagger的“实用Java”。在性能部分,建议将对象引用设置为 null 当不再需要的时候。

    在爪哇中,设置对象引用 无效的 提高性能还是垃圾收集效率?如果是这样,在什么情况下这是一个问题?容器类?对象组合?匿名内部类?

    我经常在代码中看到这个。现在这是过时的编程建议还是仍然有用?

    6 回复  |  直到 6 年前
        1
  •  69
  •   Neil Coffey    15 年前

    这在一定程度上取决于你何时考虑取消引用。

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

    除此之外,大多数情况下这个问题并没有真正出现,因为实际上您在处理集合中的对象。您通常应该考虑通过调用appropite remove()方法从列表、映射等中删除对象。

    那里的案子 曾经是 将引用设置为空的一些建议是在 内存密集型对象不再部分使用的长范围 . 例如:

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

    这里的理由是因为 OBJ 仍然在作用域中,如果没有显式地取消引用,则在 剂量测量其他() 方法完成。这就是建议 可能不再拥有现代合资企业了 :事实证明,JIT编译器可以计算出给定本地对象引用不再使用的时间点。

        2
  •  25
  •   C. K. Young    15 年前

    不,这不是过时的建议。悬空引用仍然是一个问题,特别是在实现可扩展数组容器的情况下。( ArrayList 或者类似)使用预先分配的数组。超出列表“逻辑”大小的元素应为空,否则将无法释放。

    参见有效Java第二ED,项目6:消除过时的对象引用。

        3
  •  10
  •   Thilo    15 年前

    实例字段,数组元素

    如果存在对对象的引用,则不能对其进行垃圾收集。特别是如果对象(以及它后面的整个图)很大,那么只有一个引用停止垃圾收集,而且该引用不再真正需要了,这是一种不幸的情况。

    病理案例是指将不必要的实例保留到用于配置它的整个XML DOM树、未注册的MBean或从未部署的Web应用程序对对象的单个引用(阻止卸载整个类加载器)的对象。

    因此,除非您确定保存引用本身的对象无论如何(甚至在那时)都将被垃圾收集,否则您应该将不再需要的所有内容都清空。

    作用域变量:

    如果要考虑在局部变量的作用域结束之前将其设置为空,以便垃圾收集器可以回收它并将其标记为“从现在起不可用”,则应考虑将其放在更有限的作用域中。

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

    变成

    {
      {  
         BigObject obj = ...
         doSomethingWith(obj);
      }    //         <-- obj goes out of scope
      doSomethingElse();
    }
    

    长而平的范围通常也不利于代码的易读性。为了这个目的,引进私人方法来打破局面也不是闻所未闻的。

        4
  •  5
  •   besen    15 年前

    在内存受限的环境(如手机)中,这可能很有用。通过设置空值,objetc不需要等待变量超出gc的作用域。

    然而,对于日常编程来说,这不应该是规则,除非是像ChrisJester Young引用的特殊情况。

        5
  •  1
  •   Mike Omeiri Kouider    6 年前

    首先,它并不意味着要将对象设置为 null . 我解释如下:

    List list1 = new ArrayList();
    List list2 = list1;
    

    在上面的代码段中,我们正在创建对象引用变量名 list1 属于 ArrayList 存储在内存中的对象。所以 表1 它只引用了一个变量。在第二行代码中,我们复制了 表1 list2 . 现在回到你的问题,如果我这样做:

    list1 = null;
    

    那意味着 表1 不再引用存储在内存中的任何对象,因此 表2 也没有什么可参考的。所以如果你检查 表2 :

    list2.size(); //it gives you 0
    

    所以垃圾收集器的概念出现了,它说 你不用担心释放对象所持有的内存,当我发现它不再用于程序中,并且JVM将管理我时,我会这样做。

    我希望它能澄清这个概念。

        6
  •  0
  •   Sudip Bhandari    7 年前

    这样做的原因之一是消除过时的对象引用。 你可以读课文 here.