<div dir="ltr">The static analysis is not too complicated, but there are other problems with the idea.<div><br></div><div>Allowing this feature will mean that change inside any place of the class may lead to an error at the constructor, is this feature important enough to allow that phenomenon? I don't think it is, especially when there is already a way to refactor logic into a method by returning the value:</div><div>```java</div><div>Boat(Type t) {</div><div> this.snail = getStail(t);</div><div>}</div><div>```</div><div><br></div><div>For more values you can either use a private record for the carrier object, or even a local class as a carrier.</div><div><br></div><div>About your complaints of "keep constructor stupid", a way to not get into visibility problems is to make a factory class that is a subclass of Boat, but this can make the file Boat.java a bit bloated.</div><div>Alternatively, make a mirror types inside the factory class, which allows you to translate the result of the calculations (the mirror types) into the actual types inside the constructor using a simple lookup.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jul 7, 2023 at 3:18 AM Nir Lisker <<a href="mailto:nlisker@gmail.com">nlisker@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi,<div><br></div><div>I believe that the following is a known request. Consider the class</div><div><br></div><div>class Boat {</div><div><br></div><div> final int sails;</div><div><br></div><div> Boat(Type type) {</div><div> switch (type) {</div><div> case ENGINE ->
sails = 0;</div><div> case SAIL -> sails = 2;<br></div><div> default -> sails = 1;</div><div> }</div><div> }</div><div>}</div><div><br></div><div>This is fine (and yes, can be written better). However, if I try to extract the constructor body into a private method, I get a compilation error that the final field has not been assigned. Understandable at this point.</div><div><br></div><div>In some classes that are more complex than my contrived example, the constructor's body is divided into steps ('createSails', 'createAnchor'...) that assign final fields. The current situation forces all of the code to appear in one big chunk in the constructor, instead of being able to divide the work into methods, as we usually like to do with methods. There is a known clear readability and maintenance benefit here.</div><div><br></div><div>I'm aware that there is a school of thought saying that the constructor should only do simple things, and all the preparation should be done before instantiating the class. Basically, calling createSails() etc. first and then sending the results to the constructor to just do checks and assignments. I don't always subscribe to this approach, especially since it exposes implementation details (what if the return type of createSails() should be internal to Boat only?).</div><div><br></div><div>I remember some discussion for "nested methods": allowing methods (and constructors) to contain other methods; I assume that that would be one way to solve it. One can also use simple scopes (`{ ... }`) to divide the method/constructor. However, I would like you to consider the following solution.</div><div>If the method satisfies these conditions:</div><div>1. It is private (and thus final)</div><div>2. It is called only from the/a constructor</div><div>3. It is called only once</div><div>then it may assign final fields. The last condition might not be strictly necessary because there is already a check if the final field has been assigned already. These conditions can be applied recursively, checking if the call originates in the constructor and allowing to further divide the constructors into sub-steps, but I'm willing to wait with this addition.</div><div><br></div><div>I think that this can be checked rather easily by static analysis. I CC'd Archie who has done similar work in JEP 447 (static analysis to remove unnecessary restrictions in the constructor) to weigh in. I say "rather easily" because these conditions don't require looking at the class hierarchy - they are limited to the inspected class only.</div><div><br></div><div>Thoughts?</div><div><br></div><div>- Nir</div></div>
</blockquote></div><br clear="all"><div><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr">Holo The Wise Wolf Of Yoitsu</div></div>