JEP502:该特性为预览特性,并将在Java26的JEP526做第二次预览。初看介绍,"一个持有不可变数据的对象",不就是final对象吗?
原来,它添加了对延迟不可变性的原生支持。与final相比,它延迟初始化到首次使用时赋值,不需要在构造时立即赋值;并且可以依赖运行时条件,增加了代码灵活性。
java
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字段一样进行常量折叠。
常量折叠是编译器在编译期间自动执行的一项优化操作。
java
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)
java
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原子操作)
java
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的单例模式核心就一行:
java
private static final StableValue<NewSingleton> INSTANCE = StableValue.of();
原来Java也在不断的向前追赶着,更高效,也更简洁。