有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java递归对象删除

我很难创建一个递归删除所有对象引用的方法,类如下:

class CoolObject
{
    int someData;
    CoolObject[] subObjects; // array and each element get initialized elsewhere

    void nullSubObjects()
    {
        if(subObjects != null)
        {
            for (int o = 0; o < subObjects.length; o++) 
            {  
                if (subObject[o] != null)
                {
                  subObject[o].nullSubObjects(); //returns exception here
                  subObject[o] = null;
                } 
            } 
            subObjects = null; 
        }
    }
}

Class elsewhere
{

    void update(CoolObject currentObject)
    {
        //test for creation
        if(currentObject.subObject == null && and other conditions)
        {
            currentObject.subObject = new CoolObject[52];

            for(int m = 0; m < 52; m++) 
                 currentObject.subObject[m] = new CoolObject();         
        }

        //test for deletion
        if(currentObject.subObject != null && and other conditions)
             currentObject.nullSubObjects();



        //recursive update
        if(currentObject.subObjects != null)
             for (int q = 0; q < 52; q++) update(currentObject);
     }
}

无论何时我去更新结构,它都会在循环中导致空指针异常,尽管我刚刚检查了确保子对象不是空的

为什么我会遇到这个异常

如果不显式地取消它,“someData”会阻止它们的GC吗


谢谢大家的反馈

这种实现是一种过于复杂的方法,可以确保子对象更有可能被自动GC删除。我已经决定在更高级别取消子对象数组,并调用系统。gc()

如果不这样做,我的40k程序将在删除任何内容之前超过2Gb


共 (2) 个答案

  1. # 1 楼答案

    Why am I getting this exception?

    我可以想出几个理由,为什么你会在那一点上得到一个NPE

    • 如果对象网络是循环的,那么CoolObject实例可以通过递归nullSubObjects()调用访问,而该实例已经在处理中。由于递归调用使^ {< CD3> }字段无效,当从{{CD4}}循环的中间返回时,执行^ {< CD5> }{^ }将是^ {< CD7}},您将得到NPE。

    • 如果在您执行此操作时,其他线程正在更新图形,则所有赌注都将被取消。此代码没有同步

    我还要指出,这不是真正的代码(它是不可编译的)。真正的问题可能只存在于真正的代码上


    Is there a safer way to ensure all references are removed?

    这应该避免第一个问题:

        if (subObjects != null)
        {
            CoolObject[] s = subObjects;
            subObjects = null;
            for (int o = 0; o < s.length; o++) 
            {  
                if (s[o] != null)
                {
                  s[o].nullSubObjects(); //returns exception here
                  s[o] = null;
                } 
            }
        }
    

    然而,这可能是没有必要的;见下文

    Without explicitly nullifying it, will the 'someData' prevent their GC?

    一旦对整个树/图的所有现有引用变得不可访问,整个树/图将被垃圾收集。很难想象这样一种情况,即需要将所有引用都设置为空

  2. # 2 楼答案

    您无需执行任何这些操作即可使对象成为垃圾回收对象

    当对象不再可访问时,即当对象没有可访问的引用时,对象将变成垃圾

    以以下为例:

    class A {
        int i;
    }
    
    class B {
        A a = new A();
    }
    
    class Main {
        public static void main(String[] args) {
            B b = new B();
            // point 1
            b = null;
            // point 2
        }
    }
    

    point 1,存在B类型的对象,由b引用;存在A类型的对象,由b.a引用

    您可以想象这样的参考链:

    + main
    | + object of B
      | - object of A
    

    point 2,我无法再访问类型为B的对象,因此它符合垃圾收集的条件。我也无法访问类型为A的对象,因此它也将被垃圾收集

    现在,引用链如下所示:

    + main 
    | (no references)
    
    + object of B
    | - object of A
    

    即使类型为B的对象引用了类型为A的对象,仍然无法从main访问该对象

    当程序没有实际使用的对象引用链时,对象被垃圾收集