@Getter(lazy=true)

Overview

NEW IN Lombok 0.10: You can let lombok generate a getter which will calculate a value once, the first time this getter is called, and cache it from then on. This can be useful if calculating the value takes a lot of CPU, or the value takes a lot of memory. To use this feature, create a private final variable, initialize it with the expression that's expensive to run, and annotate your field with @Getter(lazy=true). The field will be hidden from the rest of your code, and the expression will be evaluated no more than once, when the getter is first called. There are no magic marker values (i.e. even if the result of your expensive calculation is null, the result is cached) and your expensive calculation need not be thread-safe, as lombok takes care of locking.

With Lombok

01 import lombok.Getter;
02 
03 public class GetterLazyExample {
04   @Getter(lazy=trueprivate final double[] cached = expensive();
05   
06   private double[] expensive() {
07     double[] result = new double[1000000];
08     for (int i = 0; i < result.length; i++) {
09       result[i= Math.asin(i);
10     }
11     return result;
12   }
13 }

Vanilla Java

01 public class GetterLazyExample {
02   private final java.util.concurrent.AtomicReference<java.lang.Object> cached = new java.util.concurrent.AtomicReference<java.lang.Object>();
03   
04   public double[] getCached() {
05     java.lang.Object value = this.cached.get();
06     if (value == null) {
07       synchronized(this.cached) {
08         value = this.cached.get();
09         if (value == null) {
10           final double[] actualValue = expensive();
11           value = actualValue == null this.cached : actualValue;
12           this.cached.set(value);
13         }
14       }
15     }
16     return (double[])(value == this.cached ? null : value);
17   }
18   
19   private double[] expensive() {
20     double[] result = new double[1000000];
21     for (int i = 0; i < result.length; i++) {
22       result[i= Math.asin(i);
23     }
24     return result;
25   }
26 }

Supported configuration keys (in addition to those listed on @Getter's main page):

lombok.getter.lazy.flagUsage = [warning | error] (default: not set)
Lombok will flag any usage of @Getter(lazy=true) as a warning or error if configured.

Small print

You should never refer to the field directly, always use the getter generated by lombok, because the type of the field will be mangled into an AtomicReference. Do not try to directly access this AtomicReference; if it points to itself, the value has been calculated, and it is null. If the reference points to null, then the value has not been calculated. This behaviour may change in future versions. Therefore, always use the generated getter to access your field!

Other Lombok annotations such as @ToString always call the getter even if you use doNotUseGetters=true.