<div dir="ltr">HI Per. I pleasure to talk with you.<div><br></div><div>You are right about one thing but this actually makes the API less intuitive and harder to read and reason about.</div><div><br></div><div>LazyConstant<String> foo = LazyConstant.of(() -> "hello");<br><br>void main() {<br>    if (someCondition()) {// asume false<br>        foo.get();<br>    }<br>    foo.orElse("hello2"); // ...<br><br>    println(foo.get()); // This prints "hello"<br>}</div><div><br></div><div>But if one assigns foo.orElse("hello2") to a variable, the variable actually gets the "hello2" value.</div><div><br></div><div>void main() {<br>    if (someCondition()) {// asume false<br>        foo.get();<br>    }<br>    var res = foo.orElse("hello2"); // ...</div><div>    var res2 = foo.orElse("hello3");<br>    println(res); // This prints "hello2"</div><div>    println(res2);//This prints "hello3"<br>}<br></div><div><br></div><div>This is actually even more confusing and makes the API more error prone. I personally think once initialized the lazy constant should always return the same value (maybe through the .get() method only), and there should not be any possibility of getting a different values from the same instance either in the .of() static method or in any hypothetical instance method for conditional downstream logic.  I guess one could achieve the latter with the static factory method through something like this (although less elegant)</div><div><br></div><div>private class Bar{<br>    private final LazyConstant<String> foo;<br>    private Bar(Some some){<br><br>        if(some.condition){<br>            foo = LazyConstant.of(() -> "hello");<br>        }else {<br>            foo = LazyConstant.of(() -> "hello2");<br>        }<br>    }<br>}</div><div><br></div><div>Thank you for reading. This is all I have to report. </div><div><br></div><div>Best regards.</div><div><br></div><div><br></div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">El vie, 5 dic 2025 a la(s) 6:05 a.m., Per-Ake Minborg (<a href="mailto:per-ake.minborg@oracle.com">per-ake.minborg@oracle.com</a>) escribió:<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 class="msg-1330836081727153577">




<div dir="ltr">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Hi David,<br>
<br>
Thank you for trying out LazyConstant and providing feedback. That is precisely what previews are for!<br>
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
If you take a closer look at the specification of <code>LazyConstant::orElse,</code> it says that the method will
<i>never trigger initialization.</i> And so, you <i>can</i> actually be sure that in your first example,
<code>foo</code> is always initialized to "hello" (if ever initialized). It is only if foo is not initialized that the method will return "hello2" (again, without initializing foo). This is similar to how
<code>Optional</code> works.<br>
<br>
It would be possible to entirely remove the <code>orElse()</code> method from the API, and in the rare cases where an equivalent functionality is called for, rely on
<code>LazyConstant::isInitialized</code> instead.<br>
<br>
Best, Per</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div id="m_-1330836081727153577appendonsend"></div>
<div><br>
<div style="font-family:Calibri;text-align:left;color:rgb(0,0,0);margin-left:5pt;font-size:10pt">
Confidential- Oracle Internal</div>
</div>
<hr style="display:inline-block;width:98%">
<div id="m_-1330836081727153577divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> amber-dev <<a href="mailto:amber-dev-retn@openjdk.org" target="_blank">amber-dev-retn@openjdk.org</a>> on behalf of david Grajales <<a href="mailto:david.1993grajales@gmail.com" target="_blank">david.1993grajales@gmail.com</a>><br>
<b>Sent:</b> Friday, December 5, 2025 5:38 AM<br>
<b>To:</b> amber-dev <<a href="mailto:amber-dev@openjdk.org" target="_blank">amber-dev@openjdk.org</a>>; <a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Feedback about LazyConstants API (JEP526)</font>
<div> </div>
</div>
<div>
<div dir="ltr">Dear Java Dev Team, 
<div><br>
</div>
<div> I am writing to provide feedback and two specific observations regarding the LazyConstant API, which is currently a preview feature in OpenJDK 26. </div>
<div><br>
</div>
<div> I appreciate the API's direction and I think it's a good improvement compared to its first iteration; however, I see potential for improved expressiveness, particularly in conditional scenarios.</div>
<div><br>
</div>
<div><br>
</div>
<div><b>1. Proposal: Zero-Parameter `LazyConstant.of()` Overload:</b>   </div>
<div><br>
</div>
<div>Currently, the mandatory use of a factory method receiving a `Supplier` (due to the lack of a public constructor) can obscure the expressiveness of conditional or multiple-value initialization paths. **The Issue:** When looking at the declaration:</div>
<div><br>
</div>
<div>LazyConstant<String> foo = LazyConstant.of(() -> "hello");</div>
<div><br>
</div>
<div>the code gives the strong, immediate impression that the value is <b>always</b> initialized to
<code>"hello"</code>. This makes it difficult to infer that the constant might ultimately resolve to an alternative value set later via
<code>orElse()</code> or another conditional path, especially when skimming the code:</div>
<div><br>
</div>
<div>LazyConstant<String> foo = LazyConstant.of(() -> <span>
"hello"</span>); // When skimming the code it's not always obvious that this may not be the actual value </div>
<div>  </div>
<div><span><span>void</span>
<span>main</span><span>()</span>
</span>{ </div>
<div>  <span>if</span> (someCondition()) { </div>
<div>          foo.get(); <span>// Trigger initialization to "hello"</span> </div>
<div> } </div>
<div>  <span>// If someCondition is false, the final value of foo is determined here:</span> </div>
<div>  <span>var</span> res1 = foo.orElse(<span>"hello2"</span>);
<span>// ...</span> </div>
<div>}</div>
<div><br>
</div>
<div><b>My Suggestion:</b> I propose introducing a <b>zero-parameter overloaded static factory method</b>
<code>of()</code>:</div>
<div><br>
</div>
<div>LazyConstant<String> foo = LazyConstant.of();</div>
<div><br>
</div>
<div>This form explicitly communicates that the constant is initialized to an <b>
unresolved</b> state, suggesting that the value will be determined downstream by the first invocation of an initialization/computation method.</div>
<div><br>
</div>
<div>LazyConstant<String> foo = LazyConstant.of(); <span>
// Clearly unresolved</span> </div>
<div>  <span><span>void</span>
<span>main</span><span>()</span>
</span>{ </div>
<div>  <span>if</span> (someCondition()) { </div>
<div>      foo.orElse(<span>"hello"</span>); </div>
<div> } </div>
<div>  <span>var</span> res1 = foo.orElse(<span>"hello2"</span>);
<span>// ...</span> </div>
<div>}</div>
<div><br>
</div>
<div>This is specially useful for clarity when one has conditional initialization in places such as the constructor of a class. For example</div>
<div><br>
</div>
<div>
<p>private class Bar{<br>
    LazyConstant<String> foo = LazyConstant.of();<br>
    private Bar(Some some){<br>
        if(some.condition()){<br>
            foo.orElse("foo");<br>
        }<br>
        foo.orElse("foo2");<br>
    }<br>
<br>
    String computeValue() {<br>
        return "hello";<br>
    }<br>
<br>
    String computeValue2(){<br>
        return "hello2";<br>
    }<br>
}</p>
</div>
<div>
<h3>2. Method Naming Suggestion and and supplier in instance method for consistency in the API</h3>
<p>My second, much more minor observation relates to the instance method <code>orElse(T t)</code>.</p>
<p>While <code>orElse</code> fits a retrieval pattern, I personally feel that <b>
<code>compute</code></b> or <b><code>computeIfAbsent</code></b> would better express the intent of this method, as its primary function is not just to retrieve, but to trigger the computation and
<b>set the final value</b> of the constant if it is currently uninitialized. Also, as the factory of() has a supplier i think this instance method should also receive a Supplier, This not only keeps the API consistent in the usage but makes more ergonomic the
 declaration of complex initialization logic inside the method.</p>
<p><br>
</p>
<p></p>
<p></p>
<p></p>
<p>private class Bar{<br>
    LazyConstant<InitParams> foo = LazyConstant.of(InitParam::default); // Under the current API this is mandatory but in reality the value is set in the constructor, default is never really used.<br>
    private Bar(Some some){<br>
       foo.compute(some::executeCallToCacheDBAndBringInitializationParams) //Real configuration happens here</p>
<p>    }<br>
}</p>
<p>This last it's very common for initialization of configuration classes and singletons.</p>
<p><br>
</p>
<p>Thank you so much for your attention, I hope you find this feedback useful.</p>
<p>Always yours. David Grajales</p>
</div>
</div>
</div>
</div>

</div></blockquote></div>