质量外联提示 - JDK 28:值类

质量外联提示 - JDK 28:值类

💡 原文英文,约1000词,阅读约需4分钟。
📝

内容提要

OpenJDK质量组呼吁FOSS项目使用JDK 28进行测试。JEP 401将值类作为预览特性引入,启用预览后,Integer、Optional、LocalDate等30个JDK类变为值类,带来==按值比较、无法同步、反射受限等兼容性变化,记录构造器也需遵循新规则。建议项目分别在禁用和启用预览两种模式下构建测试,并将问题反馈至valhalla-dev邮件列表。

🔎

延伸解读

预览特性下的兼容性风险:代码未改,行为已变

JEP 401 将值类作为预览特性引入,启用后 30 个 JDK 类(如 Integer、Optional、LocalDate)变为值类。这意味着即使项目代码未做任何修改,只要在启用预览的 JDK 28 上运行,就可能出现行为变化。例如 == 对值对象改为按字段值比较,可能返回 true 而此前为 false;同步、反射等操作也会受限。因此,项目需在禁用和启用预览两种模式下分别测试,以发现潜在问题。

记录构造器的新编译规则:提前构造阶段限制 this 交互

启用预览特性编译时,记录构造器需遵循额外规则:构造器代码默认在提前构造阶段运行,此时对 this 的交互仅限于字段赋值。若构造器中调用实例方法等操作 this,将导致编译错误。现有紧凑构造器若包含此类语句,需重构为非紧凑形式,或调整语句顺序,先完成字段赋值并调用 super() 或 this(...) 结束提前构造,再执行原语句。

测试策略与反馈渠道:双模式构建,问题上报 valhalla-dev

文章建议具备灵活持续集成配置的项目,分别针对禁用和启用预览特性的 JDK 28 构建并测试代码库。禁用预览时行为应保持不变,但鉴于改动深度,仍可能意外影响原有行为,需留意异常。启用预览时,除预期行为差异外,若发现 JDK 意外错误,应通过 valhalla-dev 邮件列表反馈(需注册)。这有助于在预览阶段发现并修复问题。

❓

Q&A

JDK 28 中值类预览特性会影响哪些 JDK 类?

启用预览特性后,30 个 JDK 类会变为值类,包括 java.lang 中的 Integer、Long、Float、Double、Byte、Short、Character、Boolean、Number、Record;java.util 中的 Optional、OptionalInt、OptionalLong、OptionalDouble;java.time 中的 LocalDate、LocalTime、LocalDateTime、ZonedDateTime、OffsetTime、OffsetDateTime、Duration、Instant、Period、Year、YearMonth、MonthDay;以及 java.time.chrono 中的 MinguoDate、HijrahDate、JapaneseDate、ThaiBuddhistDate。

值类对 == 比较有什么影响?

值类没有身份标识,== 会按字段值比较。对于 JDK 值类的实例,== 可能在某些以前返回 false 的情况下返回 true。例如两个相同日期的 LocalDate 实例,启用值类后 x == y 会返回 true。

值类对象能用于同步或反射吗?

不能。值类对象没有对象监视器,不能用于同步,wait 和 notify 等方法不受支持,任何监视器交互会导致编译错误或 IdentityException。java.lang.ref API 和 java.util.WeakHashMap 不能用于值类对象,会抛出 IdentityException。值类对象完全不可变,对其字段调用 setAccessible 会抛出 IllegalAccessException,即使启用了 final 字段修改。

启用预览特性后,记录构造器需要遵循什么新规则?

使用 JDK 28 并启用预览特性编译时,已有的记录构造器需要遵循额外规则,可能导致新的编译错误。记录构造器代码默认在早期构造阶段运行,该阶段限制与 this 的交互,仅允许字段赋值。因此,在记录构造器中与 this 交互的语句(如调用实例方法)会导致编译错误。如果紧凑构造器包含此类语句,必须重构为非紧凑变体;非紧凑构造器中的此类语句可以删除、重构为在早期构造上下文中工作,或者先给所有字段赋值,再调用 super() 或 this(...) 结束早期构造,然后执行原先有问题的语句。

FOSS 项目应如何测试 JDK 28 的兼容性?

建议具有足够灵活持续集成设置的项目,分别在禁用和启用预览特性的模式下,针对 JDK 28 构建并测试代码库。禁用预览特性时行为应保持不变,但仍需留意意外影响;启用预览特性时,现有代码即使未修改也会开始使用新特性,可能导致行为变化。测试中发现的问题应反馈至 valhalla-dev 邮件列表。

值类与 JDK 8 引入的基于值的类有何关系?

JDK 8 引入了基于值的类(value-based classes)概念,概述了现今值类的限制,并涵盖了 Optional 类以及 java.time.* 包中的类。此后描述不断细化,例如明确提及同步限制,JDK 16 将其扩展到原始包装类。

🏷️

标签

➡️

继续阅读