Hello Dan, Thanks for throwing this together. Very interesting read.
One quick question I have -- why are Enums and Anonymous Classes removed from the list? On Wed, Jul 15, 2026 at 6:47 PM Dan Smith <[email protected]> wrote: > JEP 401 (Value Objects) provides some general advice for migrating > existing classes to be value classes. It’s a good starting point for anyone > interested in the topic. > > https://openjdk.org/jeps/401#Migrating-to-value-classes > > As long as value classes are a preview feature, they can’t generally be > adopted in the JDK libraries (which are not compiled with > `--enable-preview`). However, we felt it was important for this JEP to > provide users with a “starter kit” of some value classes out of the box, > and to ease into any migration challenges for popular classes, so we > identified a handful of JDK classes that the JEP can treat as value classes > when preview features are enabled. (This works thanks to some heroics in > the build system and deployment tooling.) > > It’s worth asking which *other* JDK API classes might want to become value > classes someday. I explored the question in conjunction with the CSR > (JDK-8339199), and want to memorialize the experience here, for future > reference. > > Here's a definition of "value candidate" I've used for some analysis: > - Not an interface, enum, or anonymous class > - Not a "namespace class" (collection of static members with no other > interesting code) > - No mutable fields > - No synchronized methods > - Has a value-candidate super (or Object) > - For our purposes here: public (up to the top level) and exported; final > or abstract > > A separate question that I didn’t explore: what about *implementation* > classes? We can cast a wider net here, because these can be > refactored—e.g., made final. Future work, perhaps something that will be > more driven by targeted interest and high-priority performance > opportunities. > > Applying the above filter to java.base, I find: > - 1 record > - 89 concrete stateful classes > - 5 concrete stateless classes > - 94 abstract stateless classe > - 18 abstract stateful classes > > Digging into these… > > > ### 1 record > > This is java.security.PEM. Most records can be made value classes, this is > no exception. This is a new API (JEP 538), and has the distinction of being > the only public record in java.base. > > We might consider adding this to our “starter kit” list in a future > preview release. > > > ### 89 concrete stateful classes > > 28 of these are the classes we've already identified for migration. > > 8 of these are a bad fit for value classes (5 are an indirectly-mutable > API; 2 are pseudo-enums; 1 is an empty identity key; 1 is a singleton). > > 10 are javax classes I didn't look at. > > 4 of these are good value class candidates, but they implement > Serializable so will need to wait for a migration plan. > - java.security.KeyPair > - java.time.temporal.ValueRange > - java.util.Currency > - java.util.UUID > > That leaves: > - java.lang: StackWalker, Runtime.Version, ScopedValue.Carrier > - java.lang.constant: DynamicCallSiteDesc, EnumDesc, VarHandleDesc > java.lang.invoke: SerializedLambda > - java.lang.module: ModuleDescriptor components (but not the class itself, > because it has a cached hashcode); ResolvedModule > - java.math: MathContext > - java.net: PasswordAuthentication, UnixDomainSocketAddress, > InetAddressResolver.LookupPolicy > - java.nio.charset: CoderResult > - java.security: 11 classes, including DomainLoadStoreParameter, some > DrbgParameters and KeyStore nested classes; a few spec classes > - java.time: some internal classes: DateTimeFormatter, DecimalStyle, > ZoneOffsetTransition, ZoneOffsetTransitionRule, ZoneRules > - java.util: HexFormat, RandomGeneratorFactory > > From this list, RuntimeVersion and HexFormat are two that struck me as > simple standalone APIs with private constructors that could readily be > added to the migration list (although neither has much of a compelling > performance use case). (I'd also add MathContext, except it has a public > constructor, so is more of a compatibility risk.) Not coincidentally, these > are also the few remaining identity classes that claim to be *value-based > classes*. Like PEM, we could consider adding these to the “starter kit” in > the future. > > Most of the others are a small part of a bigger API. They may be migration > candidates someday, but I think it would be best to tackle any value > migration as a focused standalone effort for that API. That effort would > also include thinking about near-miss candidates due to things like mutable > fields that cache hashes. > > > ### 5 concrete stateless classes > > All singletons, should remain identity classes. > > (A singleton doesn’t necessarily *need* identity, but… there’s only one of > them, so it makes no difference either way.) > > > ### 94 stateless abstract classes + 18 stateful abstract classes > > 2 of these are already identified for migration: Number and Record. > > 33 are part of a service provider API, which will generally involve > singletons and is probably best to just exclude from consideration. > > 22 represent a mutable API, despite having no mutable fields. > > 7 have a private/sealed implementation, so we know would never have value > subclasses (unless we decide to migrate those subclasses; usually it > wouldn't make sense). > > 23 are in javax packages and I didn't dig into them. > > That leaves 25 candidates: > - java.lang.classfile: CustomAttribute > - java.lang.constant: DynamicConstantDesc > - java.lang.module: ModuleReference > - java.net: 7 abstract classes that probably ought to be interfaces > - java.nio: Pipe, UserPrincipalLookupService, FileStore, Charset > - java.security: PKIXCertPathChecker, X509CRLEntry, CertPath, CRL, > Permission > - java.text: Format, CollationKey > - java.util: AbstractCollection, AbstractSet > > In the short term, for the “starter kit”, I think it may be worthwhile to > eventually add AbstractCollection and AbstractSet. (But note that > AbstractList has a protected mutable field; are we prepared to commit to > not doing something like that in the future with these other collection > classes?) > > The others could be left to adopt the feature when it’s final, although > none of them really jump out at me as obvious migration wins. (Not sure how > many of them even care about public subclassing…) > >
