Is it possible to set an Object to be null from wi

2020-06-02 13:53发布

I know that this = null is illegal.

I'm wondering if there's some other way to have an object clean itself up.

my desire is to be able to do something like this:

A a = new A();

a.doStuffAndDisappear();

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

I suspect there's no way to make this happen, but thought it would be worth asking.

标签: java
7条回答
姐就是有狂的资本
2楼-- · 2020-06-02 14:33

That is not possible, I would think. If a is an instance variable of some object x, doStuffAndDisappear somehow could get a reference to x and call a setter to set a to null. Better not to go that route as it is totally counter intuitive.

Best would be to clean up in doStuffAndDisappear (well, cant make is disappear) and make sure that no one else is referring is to a. GC should take care of rest.

查看更多
放我归山
3楼-- · 2020-06-02 14:35

I might be missing something but, since you mention that:

I'm wondering if there's some other way to have an object clean itself up.

And:

I have a self contained Widget that would be improved considerably if it could just make itself null after doing what it needs to do. Thus letting the GC clean it up and not leaving the Widget's user to have to set it to null manually.

How about, not keeping a reference to the object at all?

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

Update

Since this is not what the OP is looking for, let me expand @Perce solution:

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

Now you don't need to know the type of the parent or the field that holds A.

Working Example.


If you want to make A null its reference at every parent, just change A to hold a list of parents (List<AParent> parents), and implement a method to track parents:

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

Plus a void cleanUp() which iterate over its parents setting null:

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

Notice how this solution looks a lot like JavaBeans Bound Properties... This is not by coincidence; we are, in a way, creating a simple Event / Listener architecture to that A can notify its parents to get ride of their reference to it.

查看更多
老娘就宠你
4楼-- · 2020-06-02 14:36

Yes, it is possible if you reimplement GC in your applications. My answer is inspired by your discussion with Patricia, where you said you want to have all references to that object set to null. GC example:

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

This way you can control that there are no other refernces to your class. Your class must also contain the refernces to your GC memory only. Your example:

int cell = MyGC.new(A.class)

MyGC.get(cell).doSomething();

if (MyGC.get(cell) == null)
   --- true -----
查看更多
一夜七次
5楼-- · 2020-06-02 14:37

As everyone else has said, this simply isn't possible. If it's cleaning up resources you're after, then you might consider using a pattern such as:

class A {

    private boolean cleanedUp;

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

    public boolean isCleanedUp() {
        return cleanedUp;
    }
}

And then using it like so:

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

A better solution might be to implement the java.io.Closeable or java.lang.AutoCloseable interfaces depending on your circumstance:

class B implements AutoCloseable {

    private boolean closed;

    public boolean isClosed() {
        return closed;
    }

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

In which case you can use a try-with-resources statement:

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

Or you could even combine the two and do it that way, whichever you prefer.

Or lastly you could do it the way William Morrison explained (though I'd probably cheat and just use java.util.concurrent.atomic.AtomicReference instead of making my own class, and it comes with the added benefit of being a generified type), which, depending on your circumstance, may really be unnecessary. After all, you could always just do (even though it might seem a little odd):

A a = new A();

a.doStuffAndDisappear();
a = null;

if(a == null){
     //...
}
查看更多
Rolldiameter
6楼-- · 2020-06-02 14:45

You can't have an object set another object's reference to null like this without having them both aware of one another. Doing what you want is impossible without some legwork. I advise against the following example.

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

This will cause one value's reference to a second reference to vanish as a second reference is setting the first reference's reference to null.

查看更多
爱情/是我丢掉的垃圾
7楼-- · 2020-06-02 14:50

This neat question is technically interesting. However, considering your intent: You are attempting to force the condition of all references being null so that you can guard against the invalid use of an otherwise expired instance.

It is bad practice to assign any meaning to null.

Instead, modify (or facade if you can't modify) your A object so that some other flag is available. For example public boolean isClosed() ...

查看更多
登录 后发表回答