找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

325

积分

0

好友

44

主题
发表于 13 小时前 | 查看: 1| 回复: 0

JEP 526,即“延迟常量(第二次预览)”,已在JDK 26中完成其第二次预览。该特性旨在为Java引入“计算常量”的概念,这是一种最多初始化一次的不可变值持有者。它在提供final字段的性能与安全性优势的同时,赋予了初始化时机更大的灵活性。

本次预览的关键修订包括:将特性名称从“稳定值”更名为“延迟常量”,新名称更能体现其高层用例的意图并提升了可发现性。此外,API本身也进行了大幅简化。

从复杂控制到简洁API

最初的“稳定值”API暴露了多个底层操作,如setOrThrowtrySetorElseSet,它们提供了对初始化的细粒度控制。但根据提案,这些操作难以合理化,并且常常鼓励与API初衷背道而驰的使用模式。

JEP 526用更简单、更符合人体工程学的java.lang.LazyConstant<T>类取代了这些机制,该类仅支持基于工厂的初始化。这一重命名明确了设计意图:新的设计不再聚焦于“通过底层控制实现的稳定性”,而是强调延迟性与不可变性的结合。现在,开发者无需再借助双检锁、持有者类或可空字段等临时模式,就能表达延迟初始化逻辑。

如何使用 LazyConstant

使用新API,可以通过提供一个Supplier函数来定义一个延迟常量。计算出的值在首次访问后被缓存,且永不改变。参考以下示例:

private static final LazyConstant<Logger> LOG =
    LazyConstant.of(() -> Logger.create(MyService.class));

void run() {
    LOG.get().info("service started");
}

这种方式替代了诸如双检锁、持有者类和可空字段等旧的延迟初始化惯用法。这些模式通常需要额外的簿记工作和手动的线程安全控制。而使用LazyConstant,一旦值被初始化,JVM会将其视为真正的常量,从而开启了可变延迟初始化技术所无法实现的优化空间。

延迟集合:按需初始化的聚合结构

开发者还可以使用延迟列表和延迟映射来聚合延迟值,这些集合将每个元素存储在其各自的延迟常量中。这使得集合可以“按需”增长,而非一次性全部创建。例如,应用程序可以维护一个控制器池,而无需提前创建每个实例:

static final List<OrderController> ORDERS =
    List.ofLazy(POOL_SIZE, _ -> new OrderController());

OrderController controller() {
    long index = Thread.currentThread().threadId() % POOL_SIZE;
    return ORDERS.get((int) index);
}

每个列表元素仅在首次被访问时初始化,后续调用将返回缓存的控制器。同样的模式也适用于使用延迟映射的命名键:

static final Map<String, OrderController> ORDERS =
    Map.ofLazy(Set.of("Customers", "Internal", "Testing"),
               _ -> new OrderController());

OrderController controller() {
    return ORDERS.get(Thread.currentThread().getName());
}

这些聚合结构在支持更具表现力的访问模式的同时,提供了延迟初始化、线程安全性和JVM优化。

重要变更:不再允许 null 值

与早期预览版相比,一个值得注意的变更是null不再被允许作为计算值。设计者指出,禁止null可以消除歧义,移除常见路径中的分支,并与其他不可修改的构造保持一致。这一变更也简化了心智模型:一个LazyConstant总是会产生一个真实的值。任何将null视为合法常量的尝试现在都被视为设计错误。

设计哲学与性能影响

从“稳定值”到“延迟常量”的转变也反映了一种哲学上的调整。“稳定值”的行为有些类似于底层同步或原子原语,只是在之上叠加了不可变性。而“延迟常量”则为日常的初始化场景提供了一个高层次的抽象。这使得该特性更适用于库和框架,它们可以利用延迟常量来降低那些并非每次应用运行都会使用的组件的启动成本。

LazyConstant存储在final字段中,允许JVM在初始化后进行常量折叠,从而将不可变性的可靠性与延迟计算的优势结合起来。

JEP 526的主要关注点是开发者体验,但其性能影响同样显著。许多应用在启动期间会初始化大型对象图或昂贵资源,如日志记录器、配置对象或缓存。通过允许将这些表示为延迟常量,启动路径变得更轻量、响应更迅速。该API还保证了即使在并发环境下,初始化也最多发生一次,而无需开发者手动实现同步。对于大型系统或模块化架构,节省的成本可以快速累积。

当前状态与未来

该预览特性仍需在编译和执行时通过--enable-preview显式启用。设计者正在就简化的API接口、命名以及对实际工作负载的适用性征求反馈。根据提案,团队期望修订后的设计更接近开发者的需求:更少的机制、更精确的语义以及与JVM优化管道更好的协同。如果预览阶段证实了这一点,延迟常量可能会在未来的版本中成为平台的永久组成部分。

随着Java持续采纳那些在保持安全性的同时减少样板代码并提升性能的特性,延迟常量代表了一种自然的演进。如果最终定稿,该特性将为开发者使用了数十年的延迟初始化惯用法提供一个更可预测、更优化的替代方案,与平台追求清晰性、正确性和性能的宏观目标保持一致。

您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-3 14:19 , Processed in 0.056634 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表