Reputation: 69
I want to create a release()
method in my class.
After calling release()
, how can I set that instance to null
?
I mean this:
ABC abc = new ABC();
abc.release();
if(abc == null) Log.d("That's what I want");
then I want to check if abc
is null
.
How do I do this?
Upvotes: 1
Views: 1658
Reputation: 109567
Unfortunately not so easy. You want such a release to prevent further usage. Assigning null would lay the burden/goodwill at the API client. You want it to be in code. Maybe indirectly as:
class ABC {
void release() { ... }
void generateOutputOnce() {
...; release();
}
}
So use delegation to the real ABC object:
class ABC { // Maybe extends OriginalABC
OriginalABC abc;
ABC() {
abc = new OriginalABC();
}
public void release() {
abc = null;
}
public void generateOutputOnce() {
checkRelease();
abc.generateOutputOnce();
}
public void anyFunc() {
checkRelease();
abc.anyFunc();
}
private void checkRelease() {
if (abc == null) throw new IllegalStateException("Already released");
}
}
ABC having an interface would help; IDEs can generate stubs, also for delegates.
Upvotes: 1
Reputation: 11607
The variable abc
is an unidirectional reference. You can have as many references to an object as you like. There is no way* for the object to know about the references pointing to it.
The only way you can do something similar to your request is if the object you want to "nullify" has a reference to another object that holds the reference to the object (to nullify) itself.
Now you can set this one reference to your the object itself to null
. But this doesn't affect any other reference and thus the object may still be used and not be eligible for garbage collection.
As you can see this circular reference doesn't reveal the responsibilities and dependencies of the objects. In general circular dependencies should be avoided; a tree like structure should be preferred. Thus a release
method should not be triggered by the object itself. Instead the object should change its state, maybe to an invalid
or end of life
state, and inform other interested objects about this (e.g. via event listeners or a bus or messaging system). The objects holding the references then have to react and set the references to null
themselves.
Upvotes: 0
Reputation: 8653
At this point abc can'e be null
. becuase this = null;
is not a valid statement.
you have to explicitly make is null.
Upvotes: 0
Reputation: 69663
You can't.
References to objects are passed by-value in Java. You can't have a method which changes where the reference of the calling object is pointing to.
But what you could do is add a public boolean isReleased()
method to class ABC and replace if(abc == null)
with if (abc.isReleased())
.
Any methods which don't work anymore after an object is released should throw a custom exception when they are called after calling release()
. That would be much better debuggable than the NullPointerException
you would get when all references to the object would be null
ed instead.
Upvotes: 0
Reputation: 5604
It depends a bit on when you were thinking of nulling the reference.
If you have an object chain A->B->C, then once A is not reachable, A, B and C will all be eligible for garbage collection (assuming nothing else is referring to either B or C). There's no need, and never has been any need, to explicitly set references A->B or B->C to null, for example.
Apart from that, most of the time the issue doesn't really arise, because in reality you're dealing with objects in collections. You should generally always be thinking of removing objects from lists, maps etc by calling the appropiate remove() method.
The case where there used to be some advice to set references to null was specifically in a long scope where a memory-intensive object ceased to be used partway through the scope. For example:
{
BigObject obj = ...
doSomethingWith(obj);
obj = null; <-- explicitly set to null
doSomethingElse();
}
The rationale here was that because obj is still in scope, then without the explicit nulling of the reference, it does not become garbage collectable until after the doSomethingElse() method completes. And this is the advice that probably no longer holds on modern JVMs: it turns out that the JIT compiler can work out at what point a given local object reference is no longer used.
Upvotes: 0
Reputation: 44449
You don't have to do this from inside the instance per sé. If you remove the reference (all references) to this object then it will be automatically removed the next time the garbage collector does his rounds.
Simply do
ABC abc = new ABC(); // Create new instance and reference it with variable abc
abc = null; // remove the reference from abc; the instance is now floating around in space
You can try to explicitly call the garbage collector using System.gc()
. Last I remember reading is that this is merely an indication that you would like a GC and not an actual force but the documentation just says it 'runs the garbage collector'.
Upvotes: 4
Reputation: 1769
You can't do that. The reference to the ABC class exists outside of the class itself (within the caller) so there is no way for the instance of ABC to modify the reference.
You would have to implement some sort of state within ABC, like database connection objects do. When you close a database connection you still have a reference to the connection object, but the object is in the "closed" state and you can no longer use it (unless you reopen the connection first).
Upvotes: 0