<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 29/09/2025 21:39, Sergey Bylokhov
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:39b68d9b-7eeb-4c12-aac3-dd85d5f6a01f@amazon.com">On
      9/29/25 12:51, Maurizio Cimadamore wrote:
      <br>
      <blockquote type="cite">The point remains: lazy doesn't imply
        "only one" -- so, I don't buy that
        <br>
        Lazy<T> is "good enough" (although I agree it's much
        shorter to type --
        <br>
        which is, I think, the real argument here?)
        <br>
      </blockquote>
      <br>
      I have two points about this (and yes, naming is hard):
      <br>
       - First, why does "lazy" not imply "only once"? We already have
      an example of such an API: records. Does the word "record"
      explicitly imply that its components can only be assigned once? We
      implemented and documented it that way. Similarly, we can document
      the behavior for the new interface/class to clarify that laziness
      also means "stability".
      <br>
    </blockquote>
    Record components are not "lazy" -- they are assigned at record
    creation. Also, record is a language feature. Sure there's an API as
    well (Record) but it's very unlikely for users to use that directly.
    So I'm not sure how much of a precedent that is.<br>
    <blockquote type="cite" cite="mid:39b68d9b-7eeb-4c12-aac3-dd85d5f6a01f@amazon.com"> -
      Second, the main argument here is about the "Constant" part. The
      API is being compared to the final keyword and is positioned as an
      improvement, since it allows lazy initialization while still
      enabling the JVM to optimize everything. This optimization
      capability is emphasized by the "Constant" in the name. But if the
      field itself is not declared final, that undermines the whole
      argument.
      <br>
    </blockquote>
    <p>Final fields need to be initialized in the constructor/static
      initializer. Mutable fields can be initialized wherever you want,
      but then they don't get any stability guarantees. Lazy constants
      define (_through an API_) a holder for a new kind of field that
      can be initialized lazily, but only once (so, it is stable).</p>
    <p>The fact that, to get perfect runtime performance you need final
      on the declaration of the LazyConstant field seems, frankly,
      secondary -- and derives from the choice of modelling this as an
      API. Perhaps, in the table where we list the main differences
      between final fields, mutable fields and lazy constants we could
      drop the column on constant folding.</p>
    <p>Aside from that reference, I don't think the JEP is so focussed
      on performance and low-level details as you seem to imply? The
      only reference to constant folding happens quite late in the game:</p>
    <p>> There is, furthermore, mechanical sympathy between lazy
      constants and the Java runtime. Under the hood, the content of a
      lazy constant is stored in a non-<code>final</code> field
      annotated with the JDK-internal <a href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java#L30-L90"><code>@Stable</code></a>
      annotation. This annotation is a common feature of low-level JDK
      code. It asserts that, even though the field is non-<code>final</code>,
      the field’s value will not change after the field’s initial and
      only update. This allows the JVM to treat the content of a lazy
      constant as a true constant, provided that the field which refers
      to the lazy constant is <code>final</code>. Thus the JVM can
      apply constant-folding optimizations to code that accesses
      immutable data through multiple levels of lazy constants, e.g., <code>Application.orders().getLogger()</code>.</p>
    <p>Which seems fair, and even states that the lazy constant field
      needs to be final for this to happen (as you pointed out).<br>
    </p>
    <blockquote type="cite" cite="mid:39b68d9b-7eeb-4c12-aac3-dd85d5f6a01f@amazon.com">
      <br>
      <br>
      As for the current proposal, it feels somewhat unnatural that the
      API is split between LazyConstants and Map/List. I think it needs
      some time and experimentation to see how it plays out in practice.
      <br>
    </blockquote>
    Sure, we need to see how this plays out.<br>
    <br>
    <blockquote type="cite" cite="mid:39b68d9b-7eeb-4c12-aac3-dd85d5f6a01f@amazon.com">
      <br>
      <br>
      <blockquote type="cite">When you have lots of fields, using a lazy
        list provides quite a big win
        <br>
        compared to having separate holders (we made experiments with
        our
        <br>
        jextract tool which demonstrate this) -- because you can have a
        single
        <br>
        lambda/class for _all_ the elements. So you get the same
        performance as
        <br>
        having one holder class for each element, w/o really having one
        holder
        <br>
        for each element.
        <br>
      </blockquote>
      <br>
      This argument is overly focused on performance. It suggests that
      exposing many unrelated fields in a class is acceptable if it
      leads to better performance. While that might be beneficial for
      generated code, in manually written code, clarity might be more
      important than performance.
      <br>
    </blockquote>
    <p>I was replying to your own performance observation that
      LazyConstant and holder classes are the same. The answer is, I
      think, it depends. There will be cases where you have completely
      unrelated fields, and so you don't want to model these fields with
      a list/map -- there will be other cases where your class has 42
      similar method handles, one for each entity it wants to represent
      -- at which point the advantage of representing each field
      separately seems much less obvious. The LazyConstant API gives you
      both options.</p>
    <blockquote type="cite" cite="mid:39b68d9b-7eeb-4c12-aac3-dd85d5f6a01f@amazon.com">
      <br>
      I hope we can achieve both goals: good performance and proper
      encapsulation.
      <br>
    </blockquote>
    <p>You need to define what you mean by "encapsulation" here -- we're
      talking about private fields in a class after all, so it's not
      entirely clear to me what do you mean by "expose" and
      "encapsulation".</p>
    <p>I believe what you are after is a way to write the field
      declaration as regular field declaration (perhaps with a keyword
      sprinkled on top), and let the compiler worry about desugaring the
      code in a way that doesn't need an holder class per field.</p>
    <p>Fair, but we're in language territory again.</p>
    <p>Maurizio<br>
    </p>
  </body>
</html>