递归对象删除

时间:2014-07-05 07:12:57

标签: java recursion null

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

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);
     }
}

每当我去更新结构时,它会导致循环内部出现空指针异常,尽管我只是检查以确保subObject不为null ...

为什么我会收到此异常?

如果没有明确地将其取消,那么&#39; someData&#39;阻止他们的GC?


谢谢大家的反馈!

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

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

2 个答案:

答案 0 :(得分:1)

您不需要执行任何操作来使对象可以收集垃圾!

当一个对象不再可访问时,即当它没有可访问的引用时,它就会变成垃圾。

采用以下示例:

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获取该对象。

如果对象没有可以被程序实际使用的引用链,则会对对象进行垃圾回收。

答案 1 :(得分:0)

  

为什么我会收到此异常?

我可以想到为什么你可能会在那时获得NPE。

  • 如果对象网络是循环的,则可以通过递归CoolObject调用到达nullSubObjects()实例,同时它已被处理。由于递归调用使subObjects字段为空,因此当您从for循环中间的递归返回并执行subObject[o].nullSubObjects(); subObject时将为null并且你会得到一份NPE。

  • 如果其他线程在您执行此操作时更新图表,则所有投注均已关闭。此代码没有同步。

我还注意到这不是真正的代码(它不可编译)。真正的问题可能只存在于真实代码中。


  

是否有更安全的方法来确保删除所有引用?

这应该避免第一个问题:

    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;
            } 
        }
    }

然而,这可能是不必要的;见下文。

  

如果没有明确地废除它,'someData'会阻止他们的GC吗?

一旦所有对它的现有引用变得无法访问,整个树/图将被垃圾收集。很难想象必要的情况来取消所有像这样的引用。