Migrating the primitive boxes to values
Brian Goetz
brian.goetz at oracle.com
Fri Jan 25 18:12:51 UTC 2019
Let's take this problem from the other direction. What are the
impediments to us migrating the existing java.lang.Integer classes and
friends to being values? I think its pretty clear that "all things
being equal", this is a better choice than creating new pox classes, and
dealing with the sharp edges that entails. So, what's stopping us?
It's the usual suspects:
1. Equality. People do `==` on hopefully-interned Integer values. We
advise against it, but they do. Having these always fail would surely
break lots and lots of code.
2. System.identityHashCode. People put `Integer` in object graphs that
get serialized; serialization will put them through IdentityHashMap.
3. Nullability. These types are surely nullable; I think there's no
turning back from that.
4. Locking. While it seems dumb, there is surely code out there that
locks on Integer instances.
5. Constructor access. There are existing constructors, which we
deprecated in 9. Existing binaries will invoke them with
new/dup/invokespecial rather than the appropriate value instantiation.
My "Finding the Spirit" proposal offered a cure for 1: turn `==` into a
substitutibility test. For wrappers, this behaves as if all instances
were interned, rather than just the numbers from zero to some small
value; the spec warns that the range depends on runtime parameters.
Combined with deprecating and eventually removing the constructors, this
seems like it is a move that is within the range of the spec, and only
would affect code that is relying on accidental identity. Could we get
away with this?
My proposed cure for (2) is similar: make identityHashCode on values
return the "built-in hashCode" -- that is, the state-based hashCode that
is the default for values if you don't override hashCode.
Nullability is a migration concern, shared by other types migrating to
value types, so this is something we likely have to address regardless.
Which brings us to ... locking. The two choices are: assign locking on
values a state-based semantics (which no one really wants to do), or ...
let code that locks on Integer just break. Both are obviously squirmy
options.
Which brings me to my real point: if we go the latter route, when a big
legacy customer with a big legacy codebase has their code broken by
this, what happens next? I know its really easy to say that we'll tell
them they were making a mistake for 22 years and their bad behavior
finally caught up with them, but this answer is rarely well received in
reality.
It seems that if we can get comfortable with `==` being substitutibility
(which I still think is a kind of forced move), and with outlawing
locking on the primitive boxes -- both potentially big-ticket choices --
then we can rehabilitate the existing boxes. Which would be a nice
place to be.
More information about the valhalla-spec-observers
mailing list