Annotation Type LazyInit
String.hashCode()
). Note
that lazily initializing a non-volatile field is hard to do correctly, and one should rarely use
this. It should also only be done by developers who clearly understand the potential issues, and
then, always using the pattern as presented in the getData
method of this sample code
below:
private final String source;
@LazyInit private String data;
public String getData() {
String local = data;
if (local == null) {
data = local = expensiveCalculation(source);
}
return local;
}
private static String expensiveCalculation(String string) {
return string.replaceAll(" ", "_");
}
The need for using the local
variable is detailed in
http://jeremymanson.blogspot.com/2008/12/benign-data-races-in-java.html (see, particularly, the
part after "Now, let's break the code").
Also note that LazyInit
must not be used on 64-bit primitives (long
s and
double
s), because the Java Language Specification does not guarantee that writing to
these is atomic. Furthermore, when used for non-primitives, the non-primitive must be either
truly immutable or at least thread safe (in the Java memory model sense). And callers must
accommodate the fact that different calls to something like the above getData() method may return
different (though identically computed) objects, with different identityHashCode() values. Again,
unless you really understand this and you really need the performance benefits of
introducing the data race, do not use this construct.