> On Apr 24, 2020, at 1:08 PM, Brian Goetz <[email protected]> wrote:
> 
>> Not a bad idea, but here are two and a half alternatives we could consider:
>> 
>> (1) Simply ban use of “this” within a compact constructor.  This might seem 
>> like overkill, but it is very easy to explain: the keyword “this” is not 
>> available in a compact constructor, period.  Because the argument names 
>> shadow the field names, you don’t have access to the fields at all in a 
>> compact constructor.  If you don’t like it, write a non-compact constructor.
> 
> That's a nice clean way to do it, because under this (heh) model, `this` is 
> useless -- can't read the fields (they're DU), can't write them (cause I say 
> so), shouldn't call instance methods anyway (because the object is 
> uninitilized and therefore may be in an invalid state), and you shouldn't 
> pass `this` to alien code (because that undermines the final field guarantees 
> of the JMM.)  So if its useless, just don't utter it.  
> 
> (Which, in hindsight, might have been a good rule for _all_ constructors, if 
> there was another way to initialize the fields.  Surely would have eliminated 
> much verifier complexity.)

I wouldn't suggest a syntactic restriction on 'this'—that's a brittle way to 
try to provide guarantees about not leaking the object being instantiated. 
(What about the entities in scope? What about 'super'? What about inner class 
instantiations? It's whack-a-mole.)

The more principled thing to do is to say that the constructor appears in a 
static context. That almost works, except that you'd typically need the class 
type variables to be in scope... It's sort of a "mostly static context". I'd 
mildly prefer just prohibiting references to the fields rather than adopting 
that extra complexity.

Anyway, in terms of the wisdom of going there: it's a different model. Java 
could have been designed that way, and wasn't. But this is a special 
circumstance, maybe deserving of special treatment.

There are good use cases for calling instance methods. But they typically would 
involve refactoring code shared by constructors (less useful here, because 
everything flows to a single constructor) and relying on a subset of 
initialized fields (useless here, because you don't want the fields to be 
touched).

Early publishing of 'this' is important if you're building a circular data 
structure. That's not really the focus of records, given that the caller is 
supposed to (at least morally) have all of the fields in hand before allocating 
the record.

Anyway, whatever use cases we can come up with are corner cases, and there's a 
simple fallback for the corner cases.

Reply via email to