是否可以将Object本身设置为null?

时间:2013-08-17 21:46:42

标签: java

我知道this = null是非法的。

我想知道是否还有其他方法让对象自行清理。

我的愿望是能够做到这样的事情:

A a = new A();

a.doStuffAndDisappear();

if(a == null){
     //this is true after my doStuffAndDisappear() method.
}

我怀疑没有办法让这种情况发生,但我认为值得一提。

7 个答案:

答案 0 :(得分:16)

不,因为a引用(不是此问题标题中的对象),并且没有方法可以修改引用的值,除了定义它的方法(我假设从代码上下文a是一个局部变量)。

由于Java没有传递引用,因此无法完成您的要求:无法收集地址的引用以管理指向的地址。您可以使用包装器对象,但不确定它是什么意思。

答案 1 :(得分:5)

正如其他人所说,这根本不可能。如果它正在清理您所追求的资源,那么您可以考虑使用以下模式:

class A {

    private boolean cleanedUp;

    public void cleanUp() {
        // clean up any resources
        cleanedUp = true;
    }

    public boolean isCleanedUp() {
        return cleanedUp;
    }
}

然后像这样使用它:

A a = new A();
a.cleanUp();
if (a.isCleanedUp()) {
    ...
}

更好的解决方案可能是根据您的情况实施java.io.Closeablejava.lang.AutoCloseable接口:

class B implements AutoCloseable {

    private boolean closed;

    public boolean isClosed() {
        return closed;
    }

    @Override public void close() throws Exception {
        // clean up any resources
        closed = true;
    }
}

在这种情况下,您可以使用try-with-resources语句:

try (B b = new B()) {
    // do stuff
} catch (Exception ex) {
    // oh crap...
}

或者你甚至可以将两者结合起来,无论你喜欢哪种方式。

或者最后你可以像William Morrison所解释的那样(虽然我可能会作弊,只是使用java.util.concurrent.atomic.AtomicReference而不是自己上课,而且还带来了作为一般化类型的额外好处),根据您的情况,可能真的没必要。毕竟,你可以随时做(尽管看起来有点奇怪):

A a = new A();

a.doStuffAndDisappear();
a = null;

if(a == null){
     //...
}

答案 2 :(得分:2)

我可能会遗漏一些东西但是,因为你提到:

  

我想知道是否有其他方法让对象自行清理   起来。

  

我有一个自包含的小部件,如果有的话可以大大改进   在做了它需要做的事情后,它可以让自己为null。从而   让GC清理它并且不让Widget的用户拥有它   手动将其设置为空。

怎么样,根本不保留对象的引用?

new A().doStuffAndDisappear();
// no reference, instance of A is eligible to GC

<强>更新

由于这不是OP的目标,让我展开@Perce解决方案:

interface AHolder 
{
    void setA(A a);
}

class AParent implements AHolder {

    private A a;

    public AParent() {
        a = new A();
    }

    public void doSomething() {
        a.doStuffAndDisappear(this);
        if(a == null)
        {
            System.out.println("It is true!");
        }
    }

    public void setA(A a) {
        this.a = a;
    }
}

class A 
{
    void doStuffAndDisappear(AHolder parent) {
        parent.setA(null);
    }
}

现在您不需要知道父级的类型或包含A的字段。

Working Example


如果您希望A将其引用设置为每个父级,只需更改A以保存父级列表(List<AParent> parents),并实现跟踪父级的方法:< / p>

void addParent(AParent parent)
{
    parents.add(parent);       
}

加上void cleanUp()迭代其父项设置null:

void cleanUp()
{
    for (AParent parent : parents)
    {
        parent.setA(null);         
    }   
    parents.clear();  
} 

注意这个解决方案看起来很像JavaBeans Bound Properties ......这不是巧合;在某种程度上,我们创建了一个简单的事件/侦听器架构,A可以通知其父母获取对它的引用。

答案 3 :(得分:2)

这个简洁的问题在技术上很有趣。但是,考虑到您的意图:您试图强制所有引用的条件为null,以便您可以防止无效使用已过期的实例。

任何含义分配给null

是不好的做法

相反,修改(或者如果你不能修改门面)你的A对象,以便有一些其他标志可用。例如public boolean isClosed() ...

答案 4 :(得分:1)

我认为这是不可能的。如果a是某个对象x的实例变量,doStuffAndDisappear可能会以某种方式获得对x的引用,并调用setter将a设置为null。最好不要走这条路,因为它完全违反直觉。

最好是在doStuffAndDisappear中清理(好吧,不能让它消失),并确保没有其他人指的是a。 GC应该好好休息。

答案 5 :(得分:1)

是的,如果您在应用程序中重新实现GC,则可以。我的答案受到你与Patricia的讨论的启发,你说你希望将对该对象的所有引用设置为null。 GC示例:

class MyGC {
   byte[100000] myMemory;
   int nextFreeCell;
   myNew (int value) { }
   get (int myCell) { }
}

通过这种方式,您可以控制您的班级没有其他参考。您的类还必须包含对GC内存的引用。你的例子:

int cell = MyGC.new(A.class)

MyGC.get(cell).doSomething();

if (MyGC.get(cell) == null)
   --- true -----

答案 6 :(得分:0)

你不能让一个对象设置另一个对象对null的引用,而不是让他们彼此都知道。没有一些腿部工作,做你想做的事是不可能的。我建议不要使用以下示例。

public class A{
    A other;
    public A(A a){
        this.other = a;
        if(a!=null)
            a.other = this;
    }
    public void doSomethingAndDisappear(){
        a.other = null;
    }
}

这将导致一个值对第二个引用的引用消失,因为第二个引用将第一个引用的引用设置为null。

相关问题