<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
<div>
<blockquote type="cite">
<div>On Apr 24, 2023, at 4:18 PM, Dan Heidinga <heidinga@redhat.com> wrote:</div>
<div>
<div style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">
<br class="Apple-interchange-newline">
My misgivings around the term "default" are due to having already used it to describe interface methods with a default implementation. The term has also been used related to the default (initial) value of variables but that has no syntax associated with it.
So precedent supports its use..... a mixed result I guess? ....And I just found a section in the JLS (8.8.9) that already defines the default constructor for a class. That's even stronger precedent for reusing the term here given this is a slightly different
kind of default constructor.</div>
</div>
</blockquote>
</div>
<br>
<div>Forwarding some notes I put together about other uses of "default constructor". This exploration dampened my enthusiasm for trying to unify these different concepts—too many differences, IMHO. I think we're better off with a different keyword (currently
trying out "implicit" in the JEP text, but still open for more bikeshedding).</div>
<div><br>
</div>
<div>-----</div>
<div><br>
</div>
<div>Here are some different "default constructor" concepts that need to coexist in the language, with a list of their properties.<br>
<br>
special value class constructor:<br>
- must be explicit<br>
- must be public (maybe can relax this, but I don't want access checks in Arrays.newInstance)<br>
- distinct from an explicit constructor with an empty body (and maybe we allow overloading of both?)<br>
- no execution, can't throw; ignores field/instance initializers<br>
- not subject to final field initialization rule<br>
- gives the class a default instance (*preempting* field initializers!)<br>
- possibly able to opt in to non-atomic instance creation as well<br>
- implies can't have field circularity and can't be an inner class<br>
- TBD how encoded in class files/reflection, there's some sort of special metadata<br>
<br>
identity class default constructor:<br>
- implicit, or can be explicitly stated (e.g. for documentation) with an empty body or a 'super()' body<br>
- doesn't get implicitly provided if any other constructor is declared<br>
- compatibility constraint: lots of explicitly stated default constructors in the wild<br>
- has same/greater access than the class<br>
- includes super() call and field/instance initializers, may throw<br>
- no relationship to default instances or non-atomic instance creation<br>
- error if the class has uninitialized final fields<br>
- indistinguishable from any other no-arg constructor by class files/reflection<br>
<br>
abstract class "trivial" constructor (if absent, the class is implicitly 'identity'):<br>
- implicit, or can be explicitly stated (e.g. for documentation) with an empty body or a 'super()' body<br>
- doesn't get implicitly provided if any other constructor is declared<br>
- compatibility constraint: lots of explicitly stated "trivial" constructors in the wild<br>
- has same/greater access than the class<br>
- no relationship to default instances or non-atomic instance creation<br>
<br>
record class canonical constructor:<br>
I won't dig into it, but this has its own special behavior<br>
<br>
(As an aside, there's also "default method", which uses the keyword 'default', and means something totally different.)<br>
<br>
So, concretely, could we re-use the special value class constructor syntax in identity classes as a new way to explicitly express the default value constructor? There would be many mismatches:<br>
- it shouldn't give the class a default instance<br>
- it should do super() and run field/instance initializers<br>
- it doesn't imply any field circularity or inner class restriction<br>
- it would (somewhat surprisingly) allow final fields without explicit initialization<br>
- if it's detectable via reflection, we're retroactively saying all legacy classes need to be recompiled to get that capability, and all legacy attempts at explicit default constructors have to be rewritten<br>
<br>
Abstract classes still need to recognize legacy attempts at explicit "trivial" constructors. And record classes really want canonical constructors as a distinct concept from allowing a default instance.<br>
<br>
My conclusion is I don't think this is a good opportunity for unification. I get the interest in doing so—it is a bit much to have all of these similar concepts floating around, with subtle rules in each case—but I think the need for an explicit opt-in syntax
in value classes conflicts with the longstanding "convenience feature" treatment we've used elsewhere, and also the different semantics around code execution are hard to reconcile.</div>
</body>
</html>