JEP502:该特性为预览特性,并将在Java26的JEP526做第二次预览。初看介绍,“一个持有不可变数据的对象”,不就是final对象吗?
原来,它添加了对延迟不可变性的原生支持。与final相比,它延迟初始化到首次使用时赋值,不需要在构造时立即赋值;并且可以依赖运行时条件,增加了代码灵活性。
import java.lang.StableValue; import java.util.logging.Logger; public class OrderService { private final StableValue<Logger> logger = StableValue.of(); Logger getLogger() { // 首次调用时初始化,后续直接返回,线程安全 return logger.orElseSet(() -> Logger.getLogger(OrderService.class.getName())); } void submitOrder() { getLogger().info("正在下单..."); // ... getLogger().info("下单完成!"); } }稳定值被赋值后,引用不可更改,但对象内部状态仍然可变,赋值后JVM可像优化final字段一样进行常量折叠。
常量折叠是编译器在编译期间自动执行的一项优化操作。
public class ConstantFoldingExample { public static void main(String[] args) { final int a = 5; final int b = 10; int c = a + b; System.out.println(c); } }a+b是一个常量表达式,因为a和b都是final修饰的常量,在编译时,编译器会将这个表达式的结果(即15)直接嵌入到生成的代码中,因此运行时不需要再次计算a+b。
再看一下手搓单例模式的区别。
以前的方式:双重检查锁定(volatile + synchronized)
public class OldSingleton { private static volatile OldSingleton instance; // 私有构造 private OldSingleton() { System.out.println("[" + Thread.currentThread().getName() + "] 初始化单例..."); } // 双重检查锁定 public static OldSingleton getInstance() { // 第一次检查(无锁) if (instance == null) { synchronized (OldSingleton.class) { // 第二次检查(加锁后) if (instance == null) { instance = new OldSingleton(); } } } return instance; } public static void main(String[] args) { System.out.println("=== 单例测试 ==="); // 多线程并发测试 for (int i = 0; i < 5; i++) { new Thread(() -> { OldSingleton s = OldSingleton.getInstance(); System.out.println("获取实例: " + s.hashCode()); }, "Thread-" + i).start(); } } }执行结果:
Java 25的方式: (CAS原子操作)
import java.util.function.Supplier; public class NewSingleton { private static final StableValue<NewSingleton> INSTANCE = StableValue.of(); private NewSingleton() { System.out.println("[" + Thread.currentThread().getName() + "] 初始化单例..."); } public static NewSingleton getInstance() { return INSTANCE.orElseSet(NewSingleton::new); } // 使用Supplier接口 public static class SupplierVersion { // 直接返回Supplier,调用方无需知道StableValue存在 private static final Supplier<NewSingleton> INSTANCE = StableValue.supplier(NewSingleton::new); public static NewSingleton getInstance() { return INSTANCE.get(); } } public static void main(String[] args) { System.out.println("=== Java 25 StableValue单例测试 ==="); // 多线程并发测试 for (int i = 0; i < 5; i++) { new Thread(() -> { NewSingleton s = NewSingleton.getInstance(); System.out.println("获取实例: " + s.hashCode()); }, "Thread-" + i).start(); } // 测试Supplier版本 System.out.println("=== Supplier 版本测试 ==="); for (int i = 0; i < 3; i++) { new Thread(() -> { NewSingleton s = SupplierVersion.getInstance(); System.out.println("Supplier获取: " + s.hashCode()); }, "SupplierThread-" + i).start(); } } }执行结果:
Java25的单例模式核心就一行:
private static final StableValue<NewSingleton> INSTANCE = StableValue.of();原来Java也在不断的向前追赶着,更高效,也更简洁。