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.
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With