Reputation: 10038
I'm a beginner at Java. I was wondering, what to do in situations where a variable requires complex computation before being initialised, but once initialised, it will not change. I wanted to make the variable final, but instead of initialising it in constructor, I would rather initialise it in a method so this method can be reused later. Is there any way to achieve this?
In addition to all the requirements above, what happen if I want to compute the value of this variable only when I need it (because its computationally expensive to calculate it). What should I do in situations like this?
Upvotes: 3
Views: 107
Reputation: 11619
Look likes you need Lazy initialization. It is a performance optimization to use use when a result is considered to be expensive for some reason. The objectives is to delay an expensive computation until it is necessary and store the result of that expensive computation such that the computation do not need to repeat again.
Following is an example:
public final class Foo {
private Data data = null;
private Data expensiveComputation() {
if(data == null) { // first call to this method
Data data = new Data();
// complex computation
// store the result to data
} else {
return data;
}
}
}
As you can see data
is initialized only when it is needed.
Be careful that there will be problem if your code work in a multi-thread environment. It is because multiple threads can call the method at the same time. To prevent this we can use a synchronized
keyword:
public final class Foo {
private volatile Data data = null;
private Data expensiveComputation() {
if(data == null) { // first call to this method
synchronized(Foo.class) {
if(data == null) {
Data data = new Data();
// complex computation
// store the result to data
}
}
} else {
return data;
}
}
}
The synchronized
keyword only allow one thread can enter and initialize data
.
Upvotes: 2
Reputation: 8587
You can try the memoize supplier from Guava:
Supplier<T> something = Suppliers.memoize(new Supplier<T>() {
// heavy computation
return result.
});
something.get();
something.get(); // second call will return the memoized object.
Upvotes: 2
Reputation: 786
Unfortunately, you can't make a variable final in just any given moment. If a variable is final
it can (and must) be initialized in the constructor.
You could also do this (credit to npinti for following code):
private boolean isMutable;
private String someString;
public void setMutable(boolean value)
{
this.isMutable = value;
}
public void setSomeString(String value)
{
if (this.isMutable)
{
this.someString = value;
}
}
Upvotes: 2