Reader small image

You're reading from  Java Coding Problems - Second Edition

Product typeBook
Published inMar 2024
PublisherPackt
ISBN-139781837633944
Edition2nd Edition
Right arrow
Author (1)
Anghel Leonard
Anghel Leonard
author image
Anghel Leonard

Anghel Leonard is a Chief Technology Strategist and independent consultant with 20+ years of experience in the Java ecosystem. In daily work, he is focused on architecting and developing Java distributed applications that empower robust architectures, clean code, and high-performance. Also passionate about coaching, mentoring and technical leadership. He is the author of several books, videos and dozens of articles related to Java technologies.
Read more about Anghel Leonard

Right arrow

45. Exemplify the initialization-on-demand holder design pattern

Before we tackle the solution of implementing the initialization-on-demand holder design pattern, let’s quickly recap a few ingredients of this solution.

Static vs. non-static blocks

In Java, we can have initialization non-static blocks and static blocks. An initialization non-static block (or simply, a non-static block) is automatically called every single time we instantiate the class. On the other hand, an initialization static block (or simply, a static block) is called a single time when the class itself is initialized. No matter how many subsequent instances of that class we create, the static block will never get executed again. In code lines:

public class A {
  {
    System.out.println("Non-static initializer ...");
  }
  static {
    System.out.println("Static initializer ...");
  }
}

Next, let’s run the following test code to create three instances of A:

A a1 = new A();
A a2 = new A();
A a3 = new A();

The output reveals that the static initializer is called only once, while the non-static initializer is called three times:

Static initializer ...
Non-static initializer ...
Non-static initializer ...
Non-static initializer ...

Moreover, the static initializer is called before the non-static one. Next, let’s talk about nested classes.

Nested classes

Let’s look at a quick example:

public class A {
    private static class B { ... }
}

Nested classes can be static or non-static. A non-static nested class is referred to as an inner class; further, it can be a local inner class (declared in a method) or an anonymous inner class (class with no name). On the other hand, a nested class that is declared static is referred to as a static nested class. The following figure clarifies these statements:

Figure 2.28.png

Figure 2.28: Java nested classes

Since B is a static class declared in A, we say that B is a static nested class.

Tackling the initialization-on-demand holder design pattern

The initialization-on-demand holder design pattern refers to a thread-safe lazy-loaded singleton (single instance) implementation. Before JDK 16, we can exemplify this design pattern in code as follows (we want a single thread-safe instance of Connection):

public class Connection { // singleton
  private Connection() {
  }
  private static class LazyConnection { // holder
    static final Connection INSTANCE = new Connection();
    static {
      System.out.println("Initializing connection ..." 
        + INSTANCE);
    }
  }
  public static Connection get() {
    return LazyConnection.INSTANCE;
  }
}

No matter how many times a thread (multiple threads) calls Connection.get(), we always get the same instance of Connection. This is the instance created when we called get() for the first time (first thread), and Java has initialized the LazyConnection class and its statics. In other words, if we never call get(), then the LazyConnection class and its statics are never initialized (this is why we name it lazy initialization). And, this is thread-safe because static initializers can be constructed (here, INSTANCE) and referenced without explicit synchronization since they are run before any thread can use the class (here, LazyConnection).

JDK 16+

Until JDK 16, an inner class could contain static members as constant variables but it couldn’t contain static initializers. In other words, the following code would not compile because of the static initializer:

public class A {
  public class B {
    {
      System.out.println("Non-static initializer ...");
    }
    static {
      System.out.println("Static initializer ...");
    }
  }
}

But, starting with JDK 16, the previous code is compiled without issues. In other words, starting with JDK 16, Java inner classes can have static members and static initializers.

This allows us to tackle the initialization-on-demand holder design pattern from another angle. We can replace the static nested class, LazyConnection, with a local inner class as follows:

public class Connection { // singleton
  private Connection() {
  }
  public static Connection get() {
    class LazyConnection { // holder
      static final Connection INSTANCE = new Connection();
      static {
        System.out.println("Initializing connection ..." 
          + INSTANCE);
      }
    }
    return LazyConnection.INSTANCE;
  }
}

Now, the LazyConnection is visible only in its containing method, get(). As long as we don’t call the get() method, the connection will not be initialized.

Previous PageNext Page
You have been reading a chapter from
Java Coding Problems - Second Edition
Published in: Mar 2024Publisher: PacktISBN-13: 9781837633944
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Anghel Leonard

Anghel Leonard is a Chief Technology Strategist and independent consultant with 20+ years of experience in the Java ecosystem. In daily work, he is focused on architecting and developing Java distributed applications that empower robust architectures, clean code, and high-performance. Also passionate about coaching, mentoring and technical leadership. He is the author of several books, videos and dozens of articles related to Java technologies.
Read more about Anghel Leonard