Is it possible to set an Object to be null from within itself?

后端 未结 7 2021
情书的邮戳
情书的邮戳 2021-02-07 07:06

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 some

相关标签:
7条回答
  • 2021-02-07 07:44

    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){
         //...
    }
    
    0 讨论(0)
  • 2021-02-07 07:46

    No, because a is a reference (not an object as in this question's title) and no method can modify the value of a reference except the method in which it is defined (I assume from the code context that a is a local variable).

    Since Java doesn't have pass-by-reference, what you ask cannot be done: there's no way to collect addresses-of references in order to manage the addresses pointed to. You might use a wrapper object, but not sure what'd be the point.

    0 讨论(0)
  • 2021-02-07 07:47

    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.

    0 讨论(0)
  • 2021-02-07 07:48

    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.

    0 讨论(0)
  • 2021-02-07 08:03

    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.

    0 讨论(0)
  • 2021-02-07 08:09

    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() ...

    0 讨论(0)
提交回复
热议问题