Lazy Initialization in Java8
Tags: java, tutorial, design
Published: 2021-06-13 14:52:28

We don’t have any `Lazy<T>` initialisation functionality in Java as we have in other languages like **Scala, C#** etc. But don’t worry in **Java** we can implement the same kind of functionality by leveraging the **Lambda’s and Functional interface.**

In this example to create the lazy evaluation we will use the `Supplier<T>` interface, although same can be implemented by applying the other interface as well.

Let’s understand first, How `Supplier<T>` interface can be used to implement lazy initialisation.

`Supplier<T>` interface represents a function which does not take in any argument but produces a value of type T. Suppliers are useful when we don’t need to supply any value and obtain a result at the same time.

Definition of `Supplier<T>` interface is as below :

```java
@FunctionalInterface
public interface Supplier<T> {
 
    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
```
Lambda code of `Supplier<T>` interface is only executed when we execute the get() method of Supplier interface.

> If you create an object directly using the new operator, it eagerly creates the object where as if the same object is being created using the Supplier<T> then it will be lazy initialisation as object will be created only when we call get() method of Supplier <T> interface.

```java
String name = "Ishant"; // eager
 
Supplier<String> v2 = () -> "Ishant"; // lazy
```
Let’s see the complete working example to understand it better.

```java
package com.ishant.java8;
 
import java.util.function.Supplier;
 
class CustomObject {
    CustomObject (String value) {
        System.out.println(value);
    }
 
    public static CustomObject getObject(String value) {
        return new CustomObject(value);
    }
}
 
public class SupplierExample {
     
    public static void main(String[] args) {
        Supplier<CustomObject> customObjectSupplier = () -> CustomObject.getObject("Lazy initialization");
        CustomObject customObject = CustomObject.getObject("Eager initialisation");
        System.out.println("Supplier not called yet");
        customObjectSupplier.get();
 
    }
}
```
Output :
```java
Supplier not called yet
Lazy initialization
```
In the above output, we can see that Lazy initialisation was printer after the `Supplier<T>` **get()** method was executed.

## Memoization Issue

>Problem : Issue with the above approach is that, every time Supplier<T> get() method is called new instance of CustomObject will be created.

We can verify the same with below example.

```java
package com.ishant.java8;
 
import java.util.function.Supplier;
 
class CustomObject {
 
    private static int value = 0;
    CustomObject () {
        value++;
        System.out.println("Value : " + value);
    }
 
    public static CustomObject getObject() {
        return new CustomObject();
    }
}
 
public class SupplierExample {
 
    public static void main(String[] args) {
        Supplier<CustomObject> customObjectSupplier = () -> CustomObject.getObject();
        customObjectSupplier.get();
        customObjectSupplier.get();
        customObjectSupplier.get();
 
    }
}
```
Output :

```java
Value : 1
Value : 2
Value : 3
```

As in the output above we can see that the value have been printed thrice, which means that on every get() call a new instance of CustomObject is being created.

### How to fix this the memoization issue ?

Due to the not memoizing the instance of class issue, we won’t be able to use this Lazy initialisation technique where we need to maintain the singleton property of a class. For that what we can do is we can create another Lazy class and that class hold both a `Supplier<T>` and the value T itself:

```java
public class Lazy<T> implements Supplier<T> { 
    private final Supplier<T> supplier;
    private T value;
 
    @Override
    public T get() {
        if (value == null) {
            value = supplier.get();
        }
        return value;
    }
}
```
Let’s verify whether the above technique is maintaining the singleton property of a class or not as below :

```java
package com.ishant.java8;
 
import java.util.function.Supplier;
 
class CustomObject {
 
    private static int value = 0;
    CustomObject () {
        value++;
        System.out.println("Value : " + value);
    }
 
    public static CustomObject getObject() {
        return new CustomObject();
    }
}
 
class Lazy<T> implements Supplier<T> {
    private final Supplier<T> supplier;
    private T value;
 
    Lazy(Supplier<T> supplier) {
     this.supplier = supplier;
    }
 
    @Override
    public T get() {
        if (value == null) {
            value = supplier.get();
        }
        return value;
    }
}
 
public class SupplierExample {
 
    public static void main(String[] args) {
        Lazy<CustomObject> customObjectSupplier = new Lazy(() -> CustomObject.getObject());
        System.out.println("Call  1 : " + customObjectSupplier.get());
        System.out.println("Call  2 : " + customObjectSupplier.get());
        System.out.println("Call  3 : " + customObjectSupplier.get());
    }
}
```
Output : 

```java
Value : 1
Call  1 : com.ishant.java8.CustomObject@566776ad
Call  2 : com.ishant.java8.CustomObject@566776ad
Call  3 : com.ishant.java8.CustomObject@566776ad
```
From the output, we can simply see that Value: 1 has been printed only once and on every call the hascode of the object is same.

## Multithreading Issue :

We made a new class to lazily initialised the class and also maintained to create the only single instance of a class.

> Problem : But in the above code singleton property of class won’t be applicable in multithreading environment as two threads might come to create the instance of class at the same time and both will be bound to create new instance, in that way multiple instance of class will be created .

Let’s verify the same with the below code :

```java
package com.ishant.java8;
 
import java.util.function.Supplier;
 
class CustomObject {
 
    private static int value = 0;
    CustomObject () {
        value++;
        System.out.println("Value : " + value);
    }
 
    public static CustomObject getObject() {
        return new CustomObject();
    }
}
 
class Lazy<T> implements Supplier<T> {
    private final Supplier<T> supplier;
    private  T value;
 
    Lazy(Supplier<T> supplier) {
     this.supplier = supplier;
    }
 
    @Override
    public T get() {
        if (value == null) {
            value = supplier.get();
        }
        return value;
    }
}
 
public class SupplierExample {
 
    public static void main(String[] args) {
        Lazy<CustomObject> customObjectSupplier = new Lazy(() -> CustomObject.getObject());
 
        Runnable runnable =  () -> customObjectSupplier.get();
 
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        Thread thread3 = new Thread(runnable);
        Thread thread4 = new Thread(runnable);
 
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}
```
Output :
```java
Value : 3
Value : 3
Value : 4
Value : 3
```

As per the code output above, we can verify that value:3 and value:4 has been printed which means that multiple instance of same object has been created.

### How to fix the multithreading issue ?

To fix the multithreading issue, we can simply make the get() method synchronised so that multiple thread can’t access the same get() at the same time. Also we can make the value property as volatile so that its value is write and read form the main memory only and not from the CPU cache.

> Note : We can also implement the double check locking using synchronised block to make the code more proficient but to keep the simplicity for this code, i am just making the whole method synchronised.

Let’s see the code for above :

```java
class Lazy<T> implements Supplier<T> {
    private final Supplier<T> supplier;
    private volatile T value;
 
    Lazy(Supplier<T> supplier) {
     this.supplier = supplier;
    }
 
    @Override
    public synchronized T get() {
        if (value == null) {
            value = supplier.get();
        }
        return value;
    }
}
```
Let’s see the complete example and verify above code :

```java
package com.ishant.java8;
 
import java.util.function.Supplier;
 
class CustomObject {
 
    private static int value = 0;
    CustomObject () {
        value++;
        System.out.println("Value : " + value);
    }
 
    public static CustomObject getObject() {
        return new CustomObject();
    }
}
 
class Lazy<T> implements Supplier<T> {
    private final Supplier<T> supplier;
    private  volatile T value;
 
    Lazy(Supplier<T> supplier) {
     this.supplier = supplier;
    }
 
    @Override
    public synchronized T get() {
        if (value == null) {
            value = supplier.get();
        }
        return value;
    }
}
 
public class SupplierExample {
 
    public static void main(String[] args) {
        Lazy<CustomObject> customObjectSupplier = new Lazy(() -> CustomObject.getObject());
 
        Runnable runnable =  () -> customObjectSupplier.get();
 
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        Thread thread3 = new Thread(runnable);
        Thread thread4 = new Thread(runnable);
 
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}
```
Output :

```java
Value : 1
```
Output of the above code signify that only one instance has been created.

## Final Code for Lazy<T> Implementation :

```java
class Lazy<T> implements Supplier<T> {
    private final Supplier<T> supplier;
    private  volatile T value;
 
    Lazy(Supplier<T> supplier) {
     this.supplier = supplier;
    }
 
    @Override
    public synchronized T get() {
        if (value == null) {
            value = supplier.get();
        }
        return value;
    }
}
```

This Post was first published on my Personal blog website. If you like this post relevant, you cam further read other Post from there : https://ishantgaurav.in/

This is all from this Post, if you find anything wrong or have any other thoughts on the same , please share in the comment box below :