Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Lazy Assignment in Java

DZone 's Guide to

Lazy Assignment in Java

Learn more about lazy assignment in Java.

· Java Zone ·
Free Resource

Programmers are inherently lazy and similis simili gaudet, also like when the programs are lazy. Have you ever heard lazy loading? Or lazy singleton? (I, personally, prefer the single malt version though.) If you are programming in Scala or Kotlin, you can even evaluate expressions in a lazy way.

If you are programming in Scala, you can write:

lazy val z = "Hello"


And the expression will only be evaluated when z is accessed the first time. If you program in Kotlin, you can write something like:

val z: String by lazy { "Hello" }


And the expression will only be evaluated when z is accessed the first time.

Java does not support that lazy evaluation per se, but being a powerful language, it provides language elements that you can use to have the same result. While Scala and Kotlin give you the fish, Java teaches you to catch your own fish. (Let’s put a pin in this thought.)

What really happens in the background, when you code the above lines in Scala and/or Kotlin, is that the expression is not evaluated and the variable will not hold the result of the expression. Instead, the languages create some virtual “lambda” expressions, a ‘supplier’ that will later be used to calculate the value of the expression.

We can do that ourselves in Java. We can use a simple class, Lazy that provides the functionality:

public class Lazy implements Supplier {

final private Supplier supplier;
private boolean supplied = false;
private T value;

private Lazy(Supplier supplier) {
this.supplier = supplier;
}

public static  Lazy let(Supplier supplier) {
return new Lazy(supplier);
}

@Override
public T get() {
if (supplied) {
return value;
}
supplied = true;
return value = supplier.get();
}
}


The class has the public static method let() that can be used to define a supplier, and this supplier is invoked the first time the method get() is invoked. With this class, you can write the above examples as

var z = Lazy.let( () -> "Hello" );


By the way, it seems to be even simpler than the Kotlin version. You can use the class from the library:

com.javax0
lazylet
1.0.0


And then, you do not need to copy the code into your project. This is a micro library that contains only this class with an inner class that makes Lazy usable in a multi-thread environment.

The use is simple, as demonstrated in the unit tests:

private static class TestSupport {
int count = 0;

boolean callMe() {
count++;
return true;
}
}

...

final var ts = new TestSupport();
var z = Lazy.let(ts::callMe);
if (false && z.get()) {
Assertions.fail();
}
Assertions.assertEquals(0, ts.count);
z.get();
Assertions.assertEquals(1, ts.count);
z.get();
Assertions.assertEquals(1, ts.count);


To get the multi-thread safe version, you can use the code:

final var ts = new TestSupport();
var z = Lazy.sync(ts::callMe);
if (false && z.get()) {
Assertions.fail();
}
Assertions.assertEquals(0, ts.count);
z.get();
Assertions.assertEquals(1, ts.count);
z.get();
Assertions.assertEquals(1, ts.count);


And then, you get a Lazy supplier that can be used by multiple threads, and it is still guaranteed that the supplier passed as argument is passed only once.

Giving You a Fish or Teaching You to Fish

I said to put a pin in the note: “While Scala and Kotlin give you the fish, Java teaches you to catch your own fish.” Here is what I mean by that.

Many programmers write programs without understanding how the programs are executed. They program in Java and they write nice and working code, but they have no idea how the underlying technology works. They have no idea about the class loaders, garbage collections. Or they do, but they do not know anything about the machine code that the JIT compiler generates. Or, they even do that but they have no idea about the processor caches, different memory types, and hardware architecture. Or, they know that but have no knowledge about microelectronics and lithography and how the layout of the integrated circuits are, how the electrons move inside the semiconductor, and how quantum mechanics determines the non-deterministic inner working of the computer.

I do not say that you have to be a physicist and understand the intricate details of quantum mechanics to be a good programmer. I recommend, however, to understand a few layers below your everyday working tools. If you use Kotlin or Scala, it is absolutely OK to use the lazy structures they provide. They give a programming abstraction one level higher than what Java provides in this specific case. But it is vital to know what the implementation probably looks like. If you know how to fish, you can buy the packaged fish because then you can tell when the fish is good. If you do not know how to fish, you will rely on the mercy of those who give you the fish.

Topics:
java ,kotlin ,scala ,lazy ,lazy assignment ,jit ,compiler

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}