Lazy Loading and Caching via Sticky Cactoos Primitives

You obviously know what lazy loading
is, right? And you no doubt know about caching.
To my knowledge, there is no elegant way in Java to implement either of them. Here
is what I found out for myself with the help of Cactoos primitives.

Let's say we need an object that will encrypt some text. Speaking in
a more object-oriented way, it will encapsulate the text and become its
encrypted form. Here is how we will use it (let's create
tests first):

Now let's implement it, in a very primitive way, with one
primary
constructor. The encryption mechanism
will just add +1 to each byte in the incoming data, and will assume that
the encryption won't break anything (a very stupid
assumption, but for the sake of this example it will work):

Technically it works, but stream reading is right inside the constructor,
which is bad practice.
Primary
constructors must not do anything but attribute assignments, while secondary
ones may only create new objects.

Works great, but looks ugly. The ugliest part is these two lines of course:

this.text = null;
this.input = null;

They make the object
mutable
and they're using NULL. It's ugly,
trust me. Unfortunately, lazy loading and NULL references always come together in
classic examples.
However there is a better way to implement it.
Let's refactor our class, this time using
Scalar
from
Cactoos:

Now it looks way better. First of all, there is only one primary constructor and
two secondary ones. Second, the object is
immutable.
Third, there is still a lot
of room for
improvement:
we can add more constructors which will accept
other sources of data, for example
File or a byte array.

In a nutshell, the attribute that is supposed to be loaded in a "lazy" way
is represented inside an object as a "function"
(lambda expression in
Java 8). Until we touch that attribute, it's not loaded. Once we need
to work with it, the function gets executed and we have the result.

There is one problem with this code though. It will read the input stream
every time we call asString(), which will obviously not work, since only
the first time will the stream have the data. On every subsequent call the stream
will simply be empty. Thus, we need to make sure that this.text.value()
executes the encapsulated Scalar only once. All later calls must return the
previously calculated value. So we need to cache it. Here is how:

This StickyScalar
will make sure that only the first call to its method value()
will go through to the encapsulated Scalar. All other calls will receive
the result of the first call.

The last problem to solve is about concurrency. The code we have above is not
thread safe. If I create an instance of Encrypted5 and pass it to two threads,
which call asString() simultaneously, the result will be unpredictable,
simply because
StickyScalar
is not thread-safe. There is another primitive to help us out though, called
SyncScalar: