我很难创建一个方法,以递归方式删除对象的所有引用,如:
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。
答案 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吗?
一旦所有对它的现有引用变得无法访问,整个树/图将被垃圾收集。很难想象必要的情况来取消所有像这样的引用。