Ether Framework
Unified API docs for Ether modules
Loading...
Searching...
No Matches
Lazy.java
Go to the documentation of this file.
1package dev.rafex.ether.di;
2
3/*-
4 * #%L
5 * ether-di
6 * %%
7 * Copyright (C) 2026 Raúl Eduardo González Argote
8 * %%
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 * #L%
27 */
28
29import java.util.Objects;
30import java.util.function.Supplier;
31
32/**
33 * Thread-safe lazy initializer using double-checked locking.
34 *
35 * <p>The supplier is called at most once, on the first call to {@link #get()}.
36 * After initialization the supplier reference is cleared so the supplier itself
37 * (and any objects it closes over) can be garbage-collected.
38 *
39 * <pre>{@code
40 * var config = new Lazy<>(AppConfig::load);
41 * var database = new Lazy<>(() -> DataSource.create(config.get()));
42 * }</pre>
43 *
44 * @param <T> type of the lazily-initialized value
45 */
46public final class Lazy<T> {
47
48 private volatile T value;
49 private volatile Supplier<T> supplier;
50
51 /**
52 * Creates a new {@code Lazy} backed by the given supplier.
53 *
54 * @param supplier factory for the value; called at most once; must not return {@code null}
55 */
56 public Lazy(final Supplier<T> supplier) {
57 this.supplier = Objects.requireNonNull(supplier, "supplier");
58 }
59
60 /**
61 * Returns the lazily-initialized value, initializing it on first call.
62 *
63 * @return the value produced by the supplier
64 * @throws NullPointerException if the supplier returned {@code null}
65 */
66 public T get() {
67 T v = value;
68 if (v == null) {
69 synchronized (this) {
70 v = value;
71 if (v == null) {
72 v = Objects.requireNonNull(supplier.get(), "Lazy supplier returned null");
73 value = v;
74 supplier = null; // allow GC of the supplier and its captures
75 }
76 }
77 }
78 return v;
79 }
80
81 /**
82 * Returns {@code true} if the value has already been initialized.
83 *
84 * @return {@code true} after the first call to {@link #get()} completes
85 */
86 public boolean isInitialized() {
87 return value != null;
88 }
89}
Lazy(final Supplier< T > supplier)
Creates a new Lazy backed by the given supplier.
Definition Lazy.java:56
boolean isInitialized()
Returns true if the value has already been initialized.
Definition Lazy.java:86