Value-based Classes should not be used with operations that rely on object identity including reference equality, identity hashing, synchronization, or serialization.
JEP 401 introduces Value Classes and Objects as a preview feature in
Java 28. Many existing JDK types (such as primitive wrappers, Optional, and
java.time classes) are value-based and are migrating to become true value
classes.
Operations to avoid on value classes:
wait(), notify(), or notifyAll() cannot provide mutual
exclusion (as the runtime may freely copy or recreate instances) and throws
IdentityException.WeakReference, SoftReference, and PhantomReference track
the lifecycle of a specific object instance in memory. Because value objects
can be flattened, inlined, or rematerialized by the JVM, tracking their
lifetime is meaningless.IdentityHashMap, WeakHashMap, and builder configurations like
CacheBuilder.weakKeys(), CacheBuilder.weakValues(),
MapMaker.weakKeys(), or Caffeine.weakKeys() rely on reference identity
(==) or reference queues. Value classes will not behave correctly with
identity lookup or weak eviction.System.identityHashCode(...)System.identityHashCode computes a hash code based on object identity.
Value-based classes do not have persistent identity, so calling
System.identityHashCode on them is not equivalent to val.hashCode() and
produces unstable results across equal or re-boxed instances. Use
Objects.hashCode(val) or val.hashCode() instead.Suppress false positives by adding the suppression annotation @SuppressWarnings("ValueClassIdentity") to the enclosing element.