PrimitiveObject interface
Dan Smith
daniel.smith at oracle.com
Wed Jan 6 16:41:18 UTC 2021
Replies to some helpful feedback on the observers list:
> On Jan 6, 2021, at 4:46 AM, Gernot Neppert <mcnepp02 at googlemail.com> wrote:
>
> Hi Dan,
>
> a while ago on this mailing list, there already was a discussion about the necessity of two complementary interfaces.
>
> IIRC, consent was obtained that, since "IdentityObject" actually adds some capabilities to java.lang.Object - such as synchronization - a marker interface was warranted,
>
> whereas primitive classes do not offer anything over plain java.lang.Object which could be exploited via an explicit interface.
Yes, that was our thinking at one point. But we've since begun to think that a positive assertion about being a primitive object has merit as well. "Values *might* be primitive objects" and "values *will* be primitive objects" are two different things. While the same set of operations is supported in either case, the latter guarantees certain properties that the former does not.
That said, I wouldn't expect PrimitiveObject to be used often, because the properties it guarantees are fairly subtle and not relevant to most applications.
> Nevertheless, back to your propsal:
>
> I dare challenge your assertion about "symmetry". If we had such an interface "PrimitiveObject" - in what contexts would that appear?
>
> As you yourself wrote, it could by used as type-bounds for method arguments. Now, consider a generic method
>
> <T extends PrimitiveObject> void foo(T arg) {
>
> }
>
> Once I pass an argument of a concrete primitive type to this method, it will be automatically submitted to the "reference-projection", since the argument is of an interface-type.
>
> Question 1: is this even possible? I may have gotten this wrong, but to me the "reference-projection" implies that an object of the associated ".ref" class will be passed, which would then not implement "PrimitiveObject" in the first place!
There is only one object. There are times when the language operates on the object itself, and times when it operates on a *reference to* the object. Reference types are used when working with references.
PrimitiveObject is a reference type. A variable with type PrimitiveObject stores a reference to an instance of a primitive class. As generics are currently defined, a type argument must be a reference type that is a subtype of the bound; a type like Point.ref satisfies these constraints for 'T extends PrimitiveObject'. (We'll also be pursuing enhancements to generics to eliminate that reference type constraint, so that primitive value types like Point are acceptable type arguments, too.)
> Question 2: the erased function "foo" has an argument of an interface-type, which is a good old-fashioned Java reference. Inside foo(), in what way would I be able to exploit the fact that arg was a primitve object originally?
It still *is* a primitive object. It happens to be passed by reference.
What do you know about a PrimitiveObject? Things like:
- Its state is all final (though field values may themselves be mutable)
- Its '==' operation will be of the "heavier" variety
- Certain JVM optimizations related to escape analysis will have the opportunity to be applied
- Reflective operations will have certain behaviors, e.g. getClass has a default instance
Like I said, this list isn't particularly useful in most contexts, but I also think the bar is low enough here that it's enough to justify a complementary interface to IdentityObject.
> Some further remarks:
>
>> Certain abstract classes (e.g., those with fields) implicitly implement IdentityObject (this is not new)
>
> What would happen if such an abstract class explicitly implements PrimitiveObject? Would the compiler be required to reject compilation?
Yep. It's an error to implement both interfaces.
>> It's a (load-time?) error for a class or interface to extend both PrimitiveObject and IdentityObject
>
> Would that be necessary? Given that a conforming compiler could never generate such a class, what potential danger would be averted by introducing such a load-time check?
A non-conforming compiler can generate such classes, and we want strong guarantees about run-time behavior.
More information about the valhalla-spec-observers
mailing list