> But the other concerns remain, e.g. as to the fact that the boundary between
> reinterpreted types (Object as RefObject) and non-reinterpreted types (Object
> as top type) seems very fuzzy.
Right, which is why we’re still searching for an answer :)
We really, really want to be able to represent ref/val-ness in the type system.
Why? Ignoring pedagogical concerns (which are significant):
- If certain operations (e.g., locking) are partial, we want to be able to
provide a way to ask if the operation could succeed. Such as:
if (x instanceof RefObejct) { … lock on x … }
Saying “lock, and hope it doesn’t throw” is not a very good answer. We already
have a tool for querying the dynamic type of an object — instanceof.
- Saying that a method should only accept reference objects should be
something expressible in the method signature, as in
m(RefObject o) { … }
Types are how we do that.
- Similarly, we might want to express the above constraint generically; again,
types are the way we do that:
class Foo<T extends RefObject> { }
And, Q-world already taught us that we wanted to retain Object as the top type.
This mean, necessarily, that Object gets a little weirder; it takes on some
partly-class, partly-interface behavior.
Here’s an idea: What if we migrated `Object` to be an abstract class? The
casualty would be the code that says `new Object()`. While there’s certainly a
lot of it out there, perhaps this is something amenable to migration:
- At the source level, for N versions, `new Object()` gets a warning that says
“I’ll pretend you said `Object.newLockInstance()` or something.
- At the bytemode level, for M versions, we do something similar, likely for M
> N.
We can start this now, before Valhalla even previews.