Making Object abstract
mcnepp02 at googlemail.com
Sat May 8 13:27:48 UTC 2021
making Object abstract looks like a bold move, entailing a lot of
"special-casing" with regards to the "new Object()" expression.
And all this would still not render the entire hierarchy fully
consistent, and would still require behinde-the-scenes injection of
marker-interfaces, special treatment of "new Object()" etc...
...which makes me think: why not go the extra mile and really clean up
1. Introduce an abstract base class "Any". This would become the new
root of the entire Type-hierarchy.
2. "Any" would declare the public abstract methods that are common to
both identity-aware objects and primitive objects: toString(), equals(),
3. Have the non-abstract "Object" derive from Any, adding the methods
that are required for identity-aware objects: wait(), notify(), clone()...
4. Do away with the proposed interfaces "IdentityObject" and
"PrimitiveObject", getting rid of the automatic-versus-explicit
injection problem altogether.
5. Introduce an abstract class "Primitive" that derives from "Any" (as a
sibling to "Object"). This could add a nice "toObject()" method that
performs the reference-projection.
6. All primitive class declarations would implicity extend "Primitive",
in complete analogy to every normal class that extends "Object".
7. The cast from a primitive type to its corresponding reference-type
would become a cross-cast rather than an up-cast. It would still be
implicit, though, possibly going through the "Primitive.toObject()" method.
7. The cast from a reference-type to its corresponding primitive type
would probably warrant an explicit cast. This would also make the
possible NullPointerException less surprising.
9. The implicit bound of an unbounded wildcard '?' would remain
"Object". As a consequence, all generic types and methods would remain
fully compatible after erasure.
10. However, if the programmer wants full genericity over all possible
types, she can of course explicitly use "<? extends Any>" or "<T extends
Adavantages as I see them:
1. This would give programmers a very consistent object-model with far
less hard-to-learn corner-cases.
For example, the much-discussed problem of using a primitive object as a
monitor for synchronization would simply not exist!
2. Also, for the person who deals only with Objects (because he
considers them the root of all types), nothing will change.
Only after you've become familiar with it will you have to make
conscientious decisions when to generalize over all types, using "Any".
3. There'd be no injected interfaces leading to surprises. For example,
every java.lang.reflect.Proxy instance would continue to derive from Object.
3. The decision about reifiying generics would be fully decoupled from
this change, simply by not (yet) allowing the expression <? extends Any>
or <T extends Any>.
Am 08.05.2021 um 00:06 schrieb Dan Smith:
> I notice a number of times in current design documents that we state a rule and then have a parenthetical "except for Object, which is special". A lot of this specialness is due to Object behaving like an abstract class, even though it is not abstract.
> I think we'd have a cleaner design if we just updated Object to be abstract.
> - The expression 'new Object()' wouldn't normally be allowed, but we plan to special-case this anyway to produce an instance of IdentityObject.
> - Similarly, a 'new java/lang/Object' instruction would normally cause a InstantiationError, but we plan to special-case it.
> - Reflection would expose the ACC_ABSTRACT flag. <shrug>
> - The JVM story for opting in to primitive subclasses would need to work for class Object just as well as other abstract classes. We can design for that.
> - As long as this is a preview feature, we might need two different versions of Object.class, depending on whether --enable-preview is set. But we need to do that for Integer, etc., anyway, so should be doable.
> Am I missing anything that would be particularly disruptive?
More information about the valhalla-spec-observers