java 中的 supplier<t></t> 通过返回一个无参函数来延迟初始化对象,调用方在需要时才执行 get() 方法触发实际创建逻辑。具体做法是将对象构造过程封装在 lambda 表达式或方法引用中,仅在首次调用时实例化,后续调用可复用该实例。若需实现单例式的懒加载,可结合局部变量缓存结果,避免重复创建。

如何编写基础的 Supplier 延迟初始化代码
直接回答:通过定义一个 Supplier<string></string> 并在其 get() 方法中执行耗时操作(如数据库查询或文件读取),可以实现按需初始化。以下是一个完整的最小示例,演示了如何声明、赋值并调用 Supplier 来获取延迟初始化的字符串。

import java.util.function.Supplier;
public class LazyInitExample {
public static void main(String[] args) {
// 定义 Supplier,模拟延迟初始化
Supplier<String> lazyString = () -> {
System.out.println("Initializing...");
return "Hello, World!";
};
// 此时尚未输出 "Initializing..."
System.out.println("Before get()");
// 调用 get() 触发初始化
String result = lazyString.get();
System.out.println("Result: " + result);
// 再次调用,会重新初始化
String result2 = lazyString.get();
System.out.println("Result2: " + result2);
}
}运行上述代码,控制台输出顺序为:
1. Before get()
2. Initializing...
3. Result: Hello, World!
4. Initializing...
5. Result2: Hello, World!
立即学习“Java免费学习笔记(深入)”;
这表明每次调用 get() 都会重新执行 Lambda 体。若需仅初始化一次,需引入状态缓存。
如何实现单次调用的懒加载单例模式
直接回答:要实现类似 Optional 或单例的懒加载效果,需在 Supplier 外部维护一个 volatile 引用或使用 AtomicReference,在 get() 中进行双重检查锁定(DCL)或原子比较交换,确保多线程下仅初始化一次。以下代码展示了基于 volatile 和 DCL 的安全懒加载实现。

import java.util.function.Supplier;
import java.util.concurrent.atomic.AtomicReference;
public class SafeLazyInit {
private static final AtomicReference<String> instanceRef = new AtomicReference<>();
public static Supplier<String> getLazySupplier() {
return () -> {
String value = instanceRef.get();
if (value == null) {
synchronized (SafeLazyInit.class) {
value = instanceRef.get();
if (value == null) {
System.out.println("Creating instance...");
value = "Singleton Instance";
instanceRef.set(value);
}
}
}
return value;
};
}
public static void main(String[] args) {
Supplier<String> supplier = getLazySupplier();
System.out.println(supplier.get());
System.out.println(supplier.get());
}
}预期输出:
1. Creating instance...
2. Singleton Instance
3. Singleton Instance
第二次调用不再打印 "Creating instance...",证明初始化被延迟且仅执行一次。此模式适用于资源密集型对象的按需创建。
当 Supplier 内部抛出异常时会发生什么
直接回答:若 Supplier<t></t> 的 get() 方法在执行过程中抛出未检查异常(如 NullPointerException 或自定义 RuntimeException),该异常将直接传播给调用方,不会自动捕获或重试。调用方必须使用 try-catch 块处理潜在异常,否则程序将终止。以下代码验证了这一行为。
import java.util.function.Supplier;
public class ExceptionHandling {
public static void main(String[] args) {
Supplier<String> failingSupplier = () -> {
throw new RuntimeException("Initialization failed!");
};
try {
String result = failingSupplier.get();
System.out.println(result);
} catch (RuntimeException e) {
System.out.println("Caught exception: " + e.getMessage());
}
}
}预期输出:
Caught exception: Initialization failed!
这证实了 Supplier 不处理异常,仅负责提供值。开发者需在调用端显式管理错误流,保持函数式接口的简洁性。


















