Value-Based Classes

Brian Goetz brian.goetz at
Sat Feb 14 16:42:24 UTC 2015

> How come value-based classes are not allowed to be used for
> serialization (being an "identity sensitive operation") but still many
> such classes are serializable (e.g. [2])? I can understand both sides,
> i.e. why the limitation is necessary and why value-based classes
> should "of course" be serializable.
> Is there any insight into that tension or into plans on how to break it?

The primary tension is that serialization depends on identity to ensure 
a topology-preserving reproduction of the original object graph.  For 
example, imagine Foo is a value-based class:

Foo[] arr = new Foo[2];
arr[0] = new Foo(0);
arr[1] = new Foo(0);

Serialization promises that on deserialization of arr, elements 0 and 1 
will not be aliased.  Similarly, in:

Foo[] arr = new Foo[2];
arr[0] = new Foo(0);
arr[1] = arr[0];

Serialization promises that on deserialization of arr, elements 0 and 1 
*will* be aliased.

True value types cannot -- and don't want to -- preserve these promises. 
  So serializability is one of those things that might inhibit migrating 
a value-based class to a true value type.  Hence the warning that this 
falls outside the notion of value-based.

The intent of the value-based description is to give people guidance of 
how to write classes that could be transformed into value types in the 
future.  (Still, there's one big hole that even this attempt can't plug 
-- nullity.  Value types are not going to be nullable.  The fact that we 
can't proscribe value-based classes from being nullable is going to 
create some really nasty migration compatibility constraints.)

> #2: Implementation of equals, hashCode, toString
> How am I to understand the following sentence?
> "[Instances of a value-based class] have implementations of equals,
> hashCode, and toString which are computed solely from the instance's
> state and not from its identity or the state of any other object or
> variable;" (from [1])
> What exactly is "any other object"? Would, e.g., the value wrapped by
> an Optional count as one? If so, isn't calling equals on that value a
> computation based on its state?

The phrasing is admittedly murky; in our defense, the problem is 
intrinsically murky.  Clearly you want a class like:

final class StringHolder {
     final String s;

     // obvious ctor, factory
     // equals/hashCode that delegate to equality/hashCode of s

to be value-based.  And yet equals/hashCode depends on the state of 
"another object" (a string), at least by some interpretations.  Am I 
right that your question is "so, what's up with that?"

Precisely describing value-ness in a mutable-by-default language is 
indeed pretty tricky; just figuring out what to do with String (which is 
clearly intended to be value-like, but doesn't even meet the criteria 
for value-based) is pretty messy.  The stab we took in [1] tried to 
stake out the spirit of the idea, but probably needs some refinement.

More information about the valhalla-dev mailing list