I would like to implement lazy field initialization (or deferred initialization) without an if statement and taking advantage of lambdas. So, I would like to have the same behavior of the following Foo
property but without the if
:
class A<T>{
private T fooField;
public T getFoo(){
if( fooField == null ) fooField = expensiveInit();
return fooField;
}
}
Ignore the fact that this solution is not guaranteeing safe use for: 1) multi-threading; 2) null
as a valid value of T
.
So, to express the intention that the initialization of the fooField
is deferred until its first use I would like to declare the fooField
of the type Supplier<T>
such as:
class A<T>{
private Supplier<T> fooField = () -> expensiveInit();
public T getFoo(){
return fooField.get();
}
}
and then in the getFoo
property I would just return fooField.get()
. But now I want that next invocations to getFoo
property avoid the expensiveInit()
and just return the previous T
instance.
How can I achieve that without using an if
?
Despite naming conventions and replacing the ->
by =>
, then this example could be also considered in C#. However, NET Framework version 4 already provides a Lazy<T>
with the desired semantics.
Here's a way that also works if you want to pass arguments (which you dont have when initializing the functional interface) to your
expensiveInit
method.Usage is the same as Stuart Marks' answer:
Stuart Mark's solution, with an explicit class. (Whether this is "better" is a personal preference thing, I think.)
}
How about this? then you can do something like this by using
LazyInitializer
from Apache Commons: https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/concurrent/LazyInitializer.htmlThe approach taken by Miguel Gamboa's answer is a fine one:
It works well for one-off lazy fields. However, if more than one field needs to be initialized this way, the boilerplate would have to be copied and modified. Another field would have to be initialized like this:
If you can stand one extra method call per access after the initialization, I'd do it as follows. First, I'd write a higher-order function that returns an instance of Supplier that contains the cached value:
An anonymous class is called for here because it has mutable state, which is the cached of the initialized value.
Then, it becomes quite easy to create many lazily initialized fields:
Note: I see in the question that it stipulates "without using an
if
". It wasn't clear to me whether the concern here is over avoiding the runtime expensive of an if-conditional (really, it's pretty cheap) or whether it's more about avoiding having to repeat the if-conditional in every getter. I assumed it was the latter, and my proposal addresses that concern. If you're concerned about runtime overhead of an if-conditional, then you should also take the overhead of invoking a lambda expression into account.If you need something that approximates the behaviour of
Lazy
in C#, which gives you thread safety and a guarantee that you always get the same value, there is no straightforward way to avoidif
.You will need to use a volatile field and double checked locking. Here is the lowest memory footprint version of a class that gives you the C# behaviour:
It's not that elegant to use. You would have to create lazy values like this:
You can gain some elegance at the cost of additional memory footprint, by adding a factory method like this:
Now you can create thread safe lazy values simply like this:
You could do something along these lines :
I recently saw this as an idea by Venkat Subramaniam. I copied the code from this page.
The basic idea is that the Supplier once called, replaces itself with a simpler factory implementation that returns the initialized instance.
This was in the context of thread safe lazy initialization of a singleton, but you could also apply it to a normal field, obviously.