【问题标题】:When I remove 1 object from ArrayList in Java. What happen next?当我从 Java 中的 ArrayList 中删除 1 个对象时。接下来会发生什么?
【发布时间】:2017-07-16 04:29:24
【问题描述】:

我有一个像这样的简单数组列表: ..

ArrayList<SP> sps = new ArrayList<SP>();
sps.add(new SP("1"));
sps.add(new SP("2"));
sps.add(new SP("3"));

.. 当我从该列表中删除 1 个对象时。 接下来会发生什么? 该列表只是删除该对象的引用 然后对象自动释放该内存区域 (因为没有引用该对象的内存) 要么 该对象是由该列表直接从该内存区域释放的?

P/s:对不起,我的英语不好。

【问题讨论】:

    标签: java arraylist memory-management reference internal


    【解决方案1】:

    如果您调用ArrayList.remove(),则给定索引处的元素将从列表中删除(并且它后面的所有元素都会下移一个索引)。对象本身仍然存在,尚未释放内存。

    如果在从列表中删除对象后,您的应用程序中没有对该对象的剩余引用 - 这意味着它现在未被您的程序使用 - Garbage Collector 将自动释放与该对象关联的内存,以便它可以重复使用。

    【讨论】:

    • 我认为有一个错字,后面的元素向上移动一个索引
    • @AmitKumar 我不确定你的意思。如果您有一个三元素列表并调用list.remove(0),则索引0 处的元素将被删除,之前索引12 的两个元素现在将位于索引01 - 他们已经下移了。
    • @dimo414 ,我猜你的措辞不同,但我的意思是一样的,
    【解决方案2】:

    ArrayList 和删除的对象都会发生一些事情。

    ArrayList.remove() 被调用时,它确实会从ArrayList 中删除对该对象的引用。此外,被移除元素之前的内容会下移一位。

    如果没有其他对该对象的剩余引用,则为该对象分配的内存现在可以在称为 Garbage Collection 的自动化进程中释放

    例子:

    ArrayList<Integer> example = otherArrayList; // {2,3,10,6}
    example.remove(1);                           // Remove second element
    System.out.println(example.toString());
    
    > [2, 10, 6] 
    // The space to which '3' is allocated to is now eligible for GC
    

    不符合 GC 条件的对象示例:

    ArrayList<Integer> example = otherArrayList; // {2,3,10,6}
    int ref = example.get(1);                    // '3' is assigned to ref
    example.remove(1);                           // Remove second element
    System.out.println(example.toString());
    System.out.print(ref);                      
    
    > [2, 10, 6] 
    > 3
    
    /* Java is based on pass-by-value, but it passes references 
       when we pass existing object values. Which means the
       address space allocated for ref (and formerly example.get(1)) 
       is ineligible for GC.
    */ 
    

    【讨论】:

    • 有资格被释放。
    【解决方案3】:

    该列表只是删除该对象的引用,然后对象自动 释放该内存区域(因为没有引用该内存 该对象的)或该对象直接从该内存中释放 按该列表划分?

    JVM 不能以这种方式工作。

    1) 当一个对象被内存中的活对象引用时,它不符合 GC 的条件。

    2) 即使一个对象不再被内存中的活对象引用,内存释放也不是自动的。
    仅当垃圾收集器执行垃圾收集(次要或完整)时才会释放它。

    【讨论】:

      【解决方案4】:
      ArrayList<SP> sps = new ArrayList<SP>();
      

      这意味着,有一个ArrayList 类型为SP,并且这个ArrayList 的每个索引都是SP 类型,简而言之,它将是SP 的引用变量。

      现在当您调用new SP("1"); 时,将创建一个object to SP 并且构造函数返回该对象的引用。但是这里没有分配给new SP("1"); 的兼容引用变量。这样就无法再访问该对象了。

      但是在您的 ArrayList 中(对于相同的语句)将有一个引用来接受来自constructor of SP 的返回。因此,当您从列表中删除该对象时,它会失去其唯一的引用并有资格进行垃圾回收。

      参考:Calling methods on reference variable vs Calling methods on a new object

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-27
        • 2011-01-25
        • 1970-01-01
        • 1970-01-01
        • 2015-08-05
        • 1970-01-01
        • 1970-01-01
        • 2015-09-06
        相关资源
        最近更新 更多