【问题标题】:Java, make sure objects are being deleted when removed from arrayListJava,确保从arrayList中删除对象时正在删除
【发布时间】:2013-03-17 03:53:43
【问题描述】:

假设我正在删除一个名为“Enemy”的“死”对象。

使用这样的东西:

for(int i = 0; i < enemies.size(); i++)
    {
    Enemy en = (Enemy) enemies.get(i);
    if(en.getVisible() == true)
        en.update();
    else
        enemies.remove(i);
    }

对象从 ArrayList 中删除后是否会被删除?还是“应该”?我以前主要是在做 C++ 代码,垃圾回收让我很困惑。

有什么方法可以查看垃圾收集器是否正在删除对象?

谢谢

【问题讨论】:

  • 在java中,你不必担心这些情况。垃圾收集器会处理这个问题。
  • 不,它们不会被删除,你会得到ConcurrentModificationException :)
  • 是的。我要这么说。谢谢@denis.solonenko...梅森你甚至运行过这段代码吗?
  • 删除后尝试获取该对象,您会知道它是否已删除
  • @Mason.. 如果您想从 Collection 实现中删除项目,建议的方法是采用 Iterator 并从迭代器中删除项目。否则你会得到ConcurrentModificationException

标签: java loops arraylist garbage


【解决方案1】:

我真的很喜欢看到 C/C++ 和 Java 的整个垃圾收集惨败的反面。 Java 有自己的垃圾收集器,您无需担心内存管理 - .remove() 就足够了。

【讨论】:

  • 不是真的,如果你在其他集合中保留对敌人对象的引用并忘记清除它,你仍然可以在 Java 中泄漏内存
  • @denis.solonenko 是的,但是如果您保留对它的引用而不打算使用它,那么这只是一种不好的做法。您可以在 Java 中发生内存泄漏,但这种情况很少见,当然不像在 C 中那么容易。
  • 一方面它很酷,但我希望有一种更简单的方法可以在我不再需要对象时调用垃圾收集器来剔除对象。我想知道为什么他们没有添加类似于删除的关键字,而是“更安全”。
【解决方案2】:

如果您从 ArrayList 中删除一个对象,并且该对象没有任何其他引用,那么它将是垃圾收集器的“合格”。之后,您不必担心将其从堆中移除:JVM 会通过自动垃圾收集器来完成。

【讨论】:

    【解决方案3】:

    我认为这取决于您输入对象的方式。如果你把它保存在其他地方它应该仍然存在,但是如果你直接将它添加到 arrayList 它可能是垃圾。

    附:您的代码需要更正

    enemies.remove(i);
    enemies.remove(i--);
    

    【讨论】:

      【解决方案4】:

      回复我对ConcurrentModificationException 的评论。你不会得到它,但你的循环仍然不正确。看看:

      List<String> list = new ArrayList<String>(Arrays.asList("A","B","C","D"));
      for (int i = 0; i < list.size(); i++) {
          String s = list.get(i);
          if ("B".equals(s) || "C".equals(s)) list.remove(i);
      }
      System.out.println(list);
      

      输出:

      [A, C, D]
      

      C 未被删除,因为i 总是增加和跳过元素。

      【讨论】:

        【解决方案5】:

        在大多数情况下,您无需担心 Java 中的显式内存管理 - 只要从列表中删除后没有其他对象引用它们,垃圾收集器就会(最终)删除它们。

        如果enemies 列表中的对象占用了一些系统资源或其他需要明确处理的东西(比如文件句柄或其他东西),您需要在丢失引用之前清理它:

        Enemy enemy = enemies.remove();
        enemy.dispose(); // this is your method to clean up the internals - name it what you want
        // continue your loop here
        

        在与您的示例代码相关的注释中,您需要使用 Iterator 而不仅仅是迭代索引的 for 循环,这样您就可以正确地使用 remove 而不会遇到当前索引和列表大小方面的问题.您可能还需要考虑不同的List 实现(例如LinkedList,因为如果它很大,从ArrayList 中间插入/删除可能会变得很昂贵。

        关于你的其他问题:

        有什么方法可以查看垃圾收集器是否正在删除对象?

        当你这样做时,你可以 override the finalize method 你的班级 - be careful。另请注意,no guarantees 您的对象将被垃圾收集 - 不同的 JVM 通常管理内存略有不同,并且通常只在需要更多内存时进行垃圾收集。

        【讨论】:

          猜你喜欢
          • 2019-02-13
          • 1970-01-01
          • 2013-10-13
          • 2015-08-05
          • 2010-11-21
          • 1970-01-01
          • 2013-01-26
          • 1970-01-01
          • 2015-08-02
          相关资源
          最近更新 更多