Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

  • The use of float was meant to simplify the question but I can completely understand the confusion. The object actually being held by the weak reference is a view in an Android layout and this class lives outside the activities lifecycle.
  • total.get() should be assigned to a local value before it is evaluated
  • The statement "This does not work" was in relation to:

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.

like image 445
running-codebase Avatar asked Apr 07 '17 06:04

running-codebase


People also ask

What's the difference between Softreference and WeakReference in Java?

A Soft reference is eligible for collection by garbage collector, but probably won't be collected until its memory is needed. i.e. garbage collects before OutOfMemoryError . A Weak reference is a reference that does not protect a referenced object from collection by GC.

How do you create a weak reference in Java?

WeakReference Class In Java. When we create an object in Java, an object isn't weak by default. To create a Weak Reference Object, we must explicitly specify this to the JVM.

Why do we use Weakreferences?

Notes. The reason you need a weak reference is so that the Garbage Collector can dispose of the objects when they are no longer needed. If two objects retain a strong reference to each other, then they can't be garbage collected. This is a memory leak.

What is weak reference and strong reference in Java?

Strong - is a kind of reference, which makes the referenced object not eligible for GC. builder classes. eg - StringBuilder. Weak - is a reference which is eligible for GC. Soft - is a kind of reference whose object is eligible for GC until memory is avaiable.


2 Answers

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.

like image 97
RobCo Avatar answered Oct 14 '22 20:10

RobCo


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.

like image 31
nits.kk Avatar answered Oct 14 '22 20:10

nits.kk