Value-based Classes
What Are Value-based Classes?
Some classes, such as java.lang.Integer
and java.time.LocalDate
, are value-based. A value-based class has the following properties:
-
the class declares only final instance fields (though these may contain references to mutable objects);
-
the class's implementations of
equals
,hashCode
, andtoString
compute their results solely from the values of the class's instance fields (and the members of the objects they reference), not from the instance's identity; -
the class's methods treat instances as freely substitutable when equal, meaning that interchanging any two instances
x
andy
that are equal according toequals()
produces no visible change in the behavior of the class's methods; -
the class performs no synchronization using an instance's monitor;
-
the class does not declare (or has deprecated any) accessible constructors;
-
the class does not provide any instance creation mechanism that promises a unique identity on each method call—in particular, any factory method's contract must allow for the possibility that if two independently-produced instances are equal according to
equals()
, they may also be equal according to==
; -
the class is final, and extends either
Object
or a hierarchy of abstract classes that declare no instance fields or instance initializers and whose constructors are empty.
When two instances of a value-based class are equal (according to equals
), a program should not attempt to distinguish between their identities, whether directly via reference equality or indirectly via an appeal to synchronization, identity hashing, serialization, or any other identity-sensitive mechanism.
Synchronization on instances of value-based classes is strongly discouraged, because the programmer cannot guarantee exclusive ownership of the associated monitor.
Identity-related behavior of value-based classes may change in a future release. For example, synchronization may fail. Refer to https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/lang/doc-files/ValueBased.html
Identifying value-based classes
Within the JDK, the @jdk.internal.ValueBased
annotation is used to signal to javac
and HotSpot that a class is value-based, or that an abstract class or interface requires value-based subclasses.
@ValueBased
is applied to the following declarations in the Java Platform API and the JDK:
- The primitive wrapper classes in
java.lang
; - The class
java.lang.Runtime.Version
; - The "optional" classes in
java.util
:Optional
,OptionalInt
,OptionalLong
, andOptionalDouble
; - Many classes in the
java.time
API:Instant
,LocalDate
,LocalTime
,LocalDateTime
,ZonedDateTime
,ZoneId
,OffsetTime
,OffsetDateTime
,ZoneOffset
,Duration
,Period
,Year
,YearMonth
, andMonthDay
, and, injava.time.chrono
:MinguoDate
,HijrahDate
,JapaneseDate
, andThaiBuddhistDate
; - The interface
java.lang.ProcessHandle
and its implementation classes; - The implementation classes of the collection factories in
java.util
:List.of
,List.copyOf
,Set.of
,Set.copyOf
,Map.of
,Map.copyOf
,Map.ofEntries
, andMap.entry
.
Wherever the annotation is applied to an abstract class or interface, it is also applied to all subclasses in the JDK.
Some classes and interfaces in java.lang.constant
and jdk.incubator.foreign
have claimed to be value-based, but do not meet the revised requirements—for example, they inherit instance fields—and so cannot be migrated to be primitive classes. In this case, it's no longer appropriate to describe these as value-based classes, and their specifications have been revised. Refer to https://openjdk.org/jeps/390.