Sergey pointed out this additional benefit of RefObject: code that really 
doesn’t want to deal with values, or pay any of the taxes that arise from the 
fact that values are Object, such as acmp overhead. 

> On 4/8/19 12:58 PM, Brian Goetz wrote:
>> We never reached consensus on how to surface Ref/ValObject.
>> 
>> Here are some places we might want to use these type names:
>> 
>>  - Parameter types / variables: we might want to restrict the domain of a 
>> parameter or variable to only hold a reference, or a value:
>> 
>>     void m(RefObject ro) { … }
>> 
>>  - Type bounds: we might want to restrict the instantiation of a generic 
>> class to only hold a reference (say, because we’re going to lock on it):
>> 
>>     class Foo<T extends RefObject> { … }
>> 
>>  - Dynamic tests: if locking on a value is to throw, there must be a 
>> reasonable idiom that users can use to detect lockability without just 
>> trying to lock:
>> 
>>     if (x instanceof RefObject) {
>>         synchronized(x) { … }
>>     }
>> 
>>  - Ref- or Val-specific methods.  This one is more vague, but its 
>> conceivable we may want methods on ValObject that are members of all values.
>> 
>> 
>> There’s been three ways proposed (so far) that we might reflect these as top 
>> types:
>> 
>>  - RefObject and ValObject are (somewhat special) classes.  We spell (at 
>> least in the class file) “value class” as “class X extends ValObject”.  We 
>> implicitly rewrite reference classes at runtime that extend Object to extend 
>> RefObject instead.  This has obvious pedagogical value, but there are some 
>> (small) risks of anomalies.
>> 
>>  - RefObject and ValObject are interfaces.  We ensure that no class can 
>> implement both.  (Open question whether an interface could extend one or the 
>> other, acting as an implicit constraint that it only be implemented by value 
>> classes or reference classes.). Harder to do things like put final 
>> implementations of wait/notify in ValObject, though maybe this isn’t of as 
>> much value as it would have been if we’d done this 25 years ago.
>> 
>>  - Split the difference; ValObject is a class, RefObject is an interface.  
>> Sounds weird at first, but acknowledges that we’re grafting this on to refs 
>> after the fact, and eliminates most of the obvious anomalies.
>> 
>> No matter which way we go, we end up with an odd anomaly: “new Object()” 
>> should yield an instance of RefObject, but we don’t want Object <: RefObject 
>> for obvious reasons.  Its possible that “new Object()” could result in an 
>> instance of a _species_ of Object that implement RefObject… but our theory 
>> of species doesn’t quite go there and it seems a little silly to add new 
>> requirements just for this.
>> 
>> 
>> 

Reply via email to