<div dir="ltr">Hello!<div><br></div><div>Well, as you have reposted this, I assume that you are not against some discussion on the topic.</div><div><br></div><div>The both use-cases mentioned by Kai Hofmann are about caching some intermediate computation derived from the record fields to improve the performance of the application (they are not strictly necessary for correctness). </div><div>In his case, such cached values are computed in the constructor, which is somewhat unusual for (presumably heavy) computation. What if we only use the methods that never access these cached values? In this case, the computation will be just a waste of CPU time.</div><div>Usually, people perform heavy computations on demand, deferring the computation until it's actually necessary (e.g., String.hash field). Now, we have a perfect construct for this: LazyConstant. So I may imagine enhanced records with a new feature:</div><div><br></div><div>- private final fields in records are allowed only if their type is LazyConstant</div><div>- such fields must have an initializer like LazyConstant.of(() -> lambda)</div><div>- the initializer is guaranteed to see the record components. So we cannot use such fields in constructor prolog (or in compact constructor), before all the components are assigned</div><div>- it's assumed (though not statically checked) that such fields depend on record components only. They are always transient and not initialized after deserialization.</div><div><br></div><div>We may also devise some kind of syntactic sugar for LazyConstant fields (not only in records!). E.g. declare them like `private lazy T cached = initializer;` instead of `private final LazyConstant<T> cached = LazyConstant.of(() -> initializer);`. Having an ability to declare such fields will simplify the record specification: we can simply allow fields with 'lazy' modifier (which always implies 'final') without saying anything about type.</div><div><br></div><div>I'm not saying that it's something that we should do right now, especially taking into account that LazyConstants are still in preview. But probably something useful here could be done in the future.</div><div><br></div><div>With best regards,</div><div>Tagir Valeev</div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Thu, Dec 11, 2025 at 5:01 PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.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"><u></u>

  
  <div>
    <font size="4" face="monospace">The below was received on
      amber-spec-comments.  <br>
      <br>
      The author makes a renewed plea for final, non-component fields in
      records.  <br>
      <br>
      This point was discussed extensively during the design of records,
      so I won't recapitulate the discussion here.  </font>
    <div><br>
      <br>
      -------- Forwarded Message --------
      <table cellpadding="0" cellspacing="0" border="0">
        <tbody>
          <tr>
            <th valign="BASELINE" align="RIGHT" nowrap>Subject:
            </th>
            <td>An improvement request on records</td>
          </tr>
          <tr>
            <th valign="BASELINE" align="RIGHT" nowrap>Date: </th>
            <td>Thu, 11 Dec 2025 15:27:28 +0100</td>
          </tr>
          <tr>
            <th valign="BASELINE" align="RIGHT" nowrap>From: </th>
            <td>Kai Hofmann <a href="mailto:java@kai-hofmann.de" target="_blank"><java@kai-hofmann.de></a></td>
          </tr>
          <tr>
            <th valign="BASELINE" align="RIGHT" nowrap>To: </th>
            <td><a href="mailto:amber-spec-comments@openjdk.org" target="_blank">amber-spec-comments@openjdk.org</a></td>
          </tr>
        </tbody>
      </table>
      <br>
      <br>
      To whom it may concern,<br>
      <br>
      I am working here since some years on my OpenSource projects, and
      until now I had never a reason to made comments on Java - but now
      I feel I have to raise my voice on records:<br>
      <br>
      <br>
      Since some years I developed a library of DDD valueObjects both as
      normal Java objects and also in a parallel branch as records. At
      the moment you can find this work here:<br>
      <br>
      <a href="https://github.com/PowerStat/Validation" target="_blank">https://github.com/PowerStat/Validation</a><br>
      <br>
      But I plan to rename this project, because in the meantime the
      project name is no longer a good choice - maybe it will name
      something like ValueObjectLibrary - you will find it under my
      github repos.<br>
      <br>
      <br>
      So from my experiences I can say it is a correct design decision
      to not have instance fields within records.<br>
      <br>
      But in my opinion this thought is to simple, because private
      "final" instance fields should be possible and will be useful and
      could safe duplicated code as well as runtime!<br>
      <br>
      So the point is that final instance fields have to be initialized
      within the constructor and will be unchangeable after a record has
      been constructed - so they are harmless!<br>
      <br>
      As an example I have implemented a MACAddress class/record that
      represents a hardware mac address.<br>
      <br>
      Within the normal class implementation I split the mac address
      into it's parts only once within the construtor, later on I have
      multiple methods that work on this split parts.<br>
      <br>
      But within a record this is not possible so I have to do the split
      within every method where I need it - thats waste of code and
      runtime!<br>
      <br>
      Another example is my implementation of the ISBN13 - see
      <a href="https://en.wikipedia.org/wiki/ISBN" target="_blank">https://en.wikipedia.org/wiki/ISBN</a><br>
      <br>
      These numbers could come with 2 different formats: with or without
      separator chars in it - both formats are equal.<br>
      <br>
      So in my class implementation I would do a normalization (without
      separators) and store this one internally.<br>
      <br>
      Within a record this normalization in the construtor is not
      possible, because I could not have instance fields nor could I
      change the records parameter within the constructor because its
      already fixed :(<br>
      <br>
      So ISBN13 could not be implemented as a record!<br>
      <br>
      I vote for extending the record specification to have private
      "final" instances within it and maybe to allow to manipulate the
      construction parameters within the constructor.<br>
      <br>
      Would be nice to hear from you about this.<br>
      <br>
      <br>
      Greetings and have a nice Christmas and a Happy New Year.<br>
      <br>
      <br>
      PowerStat (Kai Hofmann)<br>
      <br>
      <br>
    </div>
  </div>

</blockquote></div>