running-codebase
running-codebase

Reputation: 998

Initialise WeakReference object to avoid null check

Given the below example code is there a way to initialise total such that I do not have to do a null check later when I use it. I am not able to pass the value into the constructor.

public class SampleCode 
{

    private WeakReference<Float> total;

    public SampleCode() {
    }

    public void setWidget(Float total) {
        this.total = new WeakReference<>(total);
    }

    public float calculatePercentage(Float count) {
        if (total == null) {
            return -1;
        }
        if (total.get() == null) {
            return -1;
        }

        return count / total.get();
    }
}

I would like to do something like this in the constructor:

this.total = new WeakReference<>(null);

But that doesn't work. Can I initialise a WeakReference in a released state or does that go against the classes purpose?

Thanks

Edit

Thanks for all the feedback.

total.get() == null evaluating to false after initialising with this.total = new WeakReference<>(null); I now understand that statement to be incorrect. This will evaluate to true. However I think it might be better to not initialise it to null and just check the null condition before access.

Upvotes: 9

Views: 6877

Answers (2)

nits.kk
nits.kk

Reputation: 5316

With the use of WeakReference you must always check for null check before using. Suppose there is an Object A whose existence depends upon some other contextual state.

If such object is passed to some class which is unknown of those contextual states then its always better to pass the object wrapped in an object of WeakReference. As the number of strong references to such object becomes 0, upon the execution of next Garbage collector cycle, the object is garbage collected. At this point the object of WeakReference will start giving null when get() is invoked on it. This is a signal to the using class (which do not know about the contextual states) that the object's life span is over.

Before using it the best way is to store the object in local variable (after invoking get()) , check for null check and then use it.

Even though if you have checked for not null against condition for weakReference.get() does not imply it can not be null the very next line. You need to store the object returned by get() in a local variable , check it for not null and then use. Remember not to store the object (returned by get()) as instance varaible as it will create the strong reference to the object. Just create the local variables and do not pass these local varaibles to other methods. Just use them there and let them die as thier scope ends.

You can wrap and pass the object using an object of WeakReference ( new WeakReference< strongReferenceOfSomeObject >() ) as method parameter. If you pass it as method parameter or Constructor parameter to the class unaware of the contextual states changes (which may decide object life span), it should not be assigned to instance variable. If it needs to be assigned to a instance variable then it must only be stored as WeakReference only.

Refer more at https://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html

P.S. For Float this can easily be solved using float and not wrapping Object of Float in a WeakReference. You do not need WeakReference for the code you have included in question. My answer above aims to provide a high level basic undertanding of WeakReference usuage in general.

Upvotes: 7

RobCo
RobCo

Reputation: 6495

You can initialise it like this:

private WeakReference<Float> total = new WeakReference<>(null);

Now the reference itself will never be null, but it's get method does return null.
Example of the new calculatePercentage method:

public float calculatePercentage(Float count) {
    Float totalF = total.get();
    if(totalF == null)
        return -1;

    return count / totalF;
}

However,
in most situations it makes very little sense to use a WeakReference<Float>. Why not just use the primitive float? Or if you really want to a Float object. Because when would the Float object really be garbage collected? I think it would only lead to inconsistent state and hard to track bugs.

Upvotes: 14

Related Questions