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.



Reply via email to