Java Cup
Inside Java

News and views from members of the Java team at Oracle

Quality Outreach Heads-up - JDK 28: Value Classes

The OpenJDK Quality Group is promoting the testing of FOSS projects with OpenJDK builds as a way to improve the overall quality of the release. This heads-up is part of a Quality Outreach update sent to the projects involved. To learn more about the program, and how-to join, please check here.

JEP 401 introduces value classes as a preview feature in JDK 28, an addition that has uncommon consequences for compatibility and can benefit from additional testing. This article begins with a high-level overview of two test regiments before explaining the JEP's compatibility implications in more detail.

Testing with JDK 28

Since the new capabilities are introduced as a preview, the JDK's behavior with preview features disabled (which is the default) should remain as-is. While unlikely, it is nonetheless possible that, due to the depth of changes, the behavior with disabled previews was unintentionally impacted. Projects testing against JDK 28 should keep an eye open for unexpected behavior.

With preview features enabled, 30 JDK classes become value classes, most notably the primitive wrapper classes like Integer and Double. This has the uncommon compatibility implication that existing code will start using the new feature despite being unchanged, which can lead to a wider range of behavioral changes. They fit into three categories:

We hence propose that projects with a sufficiently flexible continuous integration setup build and test their code bases against JDK 28 with disabled and enabled preview features.

Expected Behavior Changes

Value Classes

The following behavior changes apply if code runs on JDK 28 with enabled preview features. This is true even if the code was compiled with disabled preview features or on a version prior to 28.

The following 30 JDK classes are value classes:

Value classes lack identity, a property that can be used to tell two otherwise indistinguishable instances apart:

var x = LocalDate.of(2026, 7, 31);
var y = LocalDate.of(2026, 7, 31);

var identical = x == y;
// the result depends on value classes:
//  * without value classes, `identical` is `false`
//  * with value classes, `identical` is `true`

This impacts identity-sensitive operations:

There are more restrictions, but they only apply to custom value classes, which are beyond the scope of this article.

From a compatibility perspective, it's relevant to note that JDK 8 introduced the concept of value-based classes that outlined the restrictions of present-day value classes and encompassed the Optional classes as well as those in the java.time.* packages. Since then, the description has been refined, for example by explicitly mentioning synchronization, and JDK 16 expanded it to include the primitive wrapper classes.

Record Constructors

When preview features are enabled during compilation with JDK 28, pre-existing record constructors need to follow additional rules, which can lead to new compile errors. Non-compliant constructors that were compiled without preview features but executed with preview features, will execute as compiled.

Specifically, record constructor code will by default run during early construction, a phase that, among other restrictions, limits interaction with this to field assignments. (Details and motivation for early construction can be found in JEP 513, which finalized flexible contructor bodies.) Consequently, compiling with enabled preview features will lead to errors in record constructors where statements interact with this (e.g. by calling an instance method).

Existing compact constructors should contain no such statements as they expose the instance under construction with all fields set to null, 0, etc. to other code. If they do (and the statements can't simply be removed), the constructor must be refactored to its non-compact variant. If non-compact constructors contain such statements:

Call to Action

Build and test your project against JDK 28 and, if possible, also against JDK 28 with preview features enabled. Feedback is welcome through the valhalla-dev mailing list (registration required). For much more details on this proposed change as well as the compatibility implications described above, check JEP 401.

~