<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>Hit send too fast...</p>
<p>Yes, orElse alone can't set/compute the uninitialized value. So
that's a problem (as you observed)<br>
</p>
<p>But orElse can't also be explained in terms of get() -- unless
you accept doing a double access of the underlying storage.</p>
<p>Uplevelling, I believe the fact that, in the current form,
neither API sits cleanly on top of the other is probably a part of
the problem highlighted in this discussion.</p>
<p>Maurizio<br>
</p>
<div class="moz-cite-prefix">On 09/12/2025 11:22, Maurizio
Cimadamore wrote:<br>
</div>
<blockquote type="cite" cite="mid:37152b24-6f4c-4fb9-a2f8-c444d3be58e6@oracle.com">
<p><br>
</p>
<div class="moz-cite-prefix">On 09/12/2025 11:15, Anatoly
Kupriyanov wrote:<br>
</div>
<blockquote type="cite" cite="mid:CAGwStpBdf5Wt_Yw7_t1=rDxUMfiAj=zPn4ba4BAL22H9C4gVNA@mail.gmail.com">
<div dir="auto">
<div>That's seems exactly opposite. The `get` returns initial
value always making the constant initialised by calling
compute.</div>
<div dir="auto">The `orElse(v)` is a shortcut for
`c.isInitialized() ? c.get() : v`.</div>
</div>
</blockquote>
<p>Not really :-)</p>
<p>c.isInitialized also calls `getAcquire` internally (so your
snippet would end up calling getAcquire twice in some paths,
once for isInitialized, and another for get).<br>
</p>
<p>Technically, get() can be explained as:</p>
<p>V value = lazyConstant.orElse(sentinel)<br>
if (value == sentinel) throw new NoSuchElementException<br>
</p>
<p>That performs only one call to getAcquire, not two.</p>
<p>(We don't implement it exactly this way, but we could).</p>
<p>Maurizio<br>
</p>
<blockquote type="cite" cite="mid:CAGwStpBdf5Wt_Yw7_t1=rDxUMfiAj=zPn4ba4BAL22H9C4gVNA@mail.gmail.com">
<div dir="auto">
<div><br>
</div>
<div data-smartmail="gmail_signature">WBR, Anatoly.</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Tue, 9 Dec 2025, 10:25
Maurizio Cimadamore, <<a href="mailto:maurizio.cimadamore@oracle.com" target="_blank" rel="noreferrer" moz-do-not-send="true" class="moz-txt-link-freetext">maurizio.cimadamore@oracle.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>
<p>I agree with most of the conclusions in this thread.</p>
<p><br>
</p>
<p>One small nit is that, in reality, `orElse` is a
"primitive" in disguise. E.g. you can implement `get` in
terms of `orElse` but not the other way around (unless
you are willing to do _two_ accessed to the underlying
value). So, while we could drop it, we would also lose
something (which is why we decided to keep it, at least
for now).</p>
<p><br>
</p>
<p>Maurizio<br>
</p>
<p><br>
</p>
<p><br>
</p>
<div>On 08/12/2025 12:31, Per-Ake Minborg wrote:<br>
</div>
<blockquote type="cite">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
So, it is nice that folks seem to agree that <code>LazyConstant</code> should
only compute and initialize its contents from the
Supplier/lambda given at declaration time. The <code>orElse</code> method
seems to blur the contours of <code>LazyConstant</code> ,
and so, as previously said, we might consider removing
the method altogether in the next preview. <br>
<br>
It is also a fact that many have identified a need for
"something else more low-level" that supports a more
imperative programming model when working with
constants that are lazily set. We do not rule out that
such a thing might appear in a future JDK version.<br>
<br>
Best, Per</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_2056141226387924638m_-7781291897711540359divRplyFwdMsg" dir="ltr"><font style="font-size:11pt" face="Calibri, sans-serif" color="#000000"><b>From:</b> David Alayachew <a href="mailto:davidalayachew@gmail.com" rel="noreferrer noreferrer" target="_blank" moz-do-not-send="true"><davidalayachew@gmail.com></a><br>
<b>Sent:</b> Friday, December 5, 2025 2:51 PM<br>
<b>To:</b> Red IO <a href="mailto:redio.development@gmail.com" rel="noreferrer noreferrer" target="_blank" moz-do-not-send="true"><redio.development@gmail.com></a><br>
<b>Cc:</b> david Grajales <a href="mailto:david.1993grajales@gmail.com" rel="noreferrer noreferrer" target="_blank" moz-do-not-send="true"><david.1993grajales@gmail.com></a>;
Per-Ake Minborg <a href="mailto:per-ake.minborg@oracle.com" rel="noreferrer noreferrer" target="_blank" moz-do-not-send="true"><per-ake.minborg@oracle.com></a>;
amber-dev <a href="mailto:amber-dev@openjdk.org" rel="noreferrer noreferrer" target="_blank" moz-do-not-send="true"><amber-dev@openjdk.org></a>;
core-libs-dev <a href="mailto:core-libs-dev@openjdk.org" rel="noreferrer noreferrer" target="_blank" moz-do-not-send="true"><core-libs-dev@openjdk.org></a><br>
<b>Subject:</b> [External] : Re: Feedback about
LazyConstants API (JEP526)</font>
<div> </div>
</div>
<div>
<div dir="auto">
<div dir="auto">Caveat -- I have only used the Java
25 version of this library.</div>
<div dir="auto"><br>
</div>
I agree that the name orElse() is not intuitive. It
was made more intuitive by the existence of
orElseSet(). In its absence, changing the name makes
sense.
<div dir="auto"><br>
</div>
<div dir="auto">Though, I'm definitely open to just
removing the method. This is easy enough to
accomplish ourselves. Would prefer a rename
though.</div>
</div>
<br>
<div>
<div dir="ltr">On Fri, Dec 5, 2025, 8:32 AM Red IO
<<a href="mailto:redio.development@gmail.com" rel="noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">redio.development@gmail.com</a>>
wrote:<br>
</div>
<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="auto">Hi David,
<div dir="auto">As par already said the orElse
method doesn't initializes the LazyConstant. </div>
<div dir="auto">It just checks rather the value
is init and if not calls the supplier to get a
substitute for the missing constant. </div>
<div dir="auto">Example:</div>
<div dir="auto">LazyConstant<String> x =
LazyConstant.of(() -> "Const");</div>
<div dir="auto">var uninit1 = x.orElse(() ->
"substitute 1");</div>
<div dir="auto">var uninit2 = x.orElse(() ->
"substitute 2");</div>
<div dir="auto">var init1 = x.get();</div>
<div dir="auto">var init2 = x.orElse(() ->
"substitute 3");</div>
<div dir="auto">uninit1 and uninit2 get the
substitute 1/2</div>
<div dir="auto">And init1 and init2 get Const. </div>
<div dir="auto"><br>
</div>
<div dir="auto">This is surprising if you expect
it to be a way to init it with an alternative
value. </div>
<div dir="auto"><br>
</div>
<div dir="auto">My suggestion would to make the
separation clear and allow for another use
case by spliting this api in 2 parts:</div>
<div dir="auto">One class LazyConstant </div>
<div dir="auto">Takes a Supplier in static
factory and exposes get() </div>
<div dir="auto"><br>
</div>
<div dir="auto">And</div>
<div dir="auto">Class LazyInit</div>
<div dir="auto">Which takes no arguments in the
static factory and takes a supplier in the get
method that gets called when get is called for
the first time. </div>
<div dir="auto">In this case the source for the
constant can be any piece of code that has
access to the LazyConstant. This might be
desired in some cases. In cases where it's not
the other version can be used. </div>
<div dir="auto"><br>
</div>
<div dir="auto">This split makes it clear from
which context the constant is initialized from
(consumer or at declaration) </div>
<div dir="auto"><br>
</div>
<div dir="auto">Mixing those 2 or having methods
that appear to do this is rather confusing. </div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">One solution for the "i might
not want to init the constant" case the
"orElse" method is meant to be is to have a
method "tryGet" which returns Optional
instead. This makes it clear that the value
might not be there and is not initialized when
calling the method. Nobody expects to init the
constant when calling orElse on a returned
Optional. </div>
<div dir="auto"><br>
</div>
<div dir="auto">My 2 suggestions here are
completely independent and should be viewed as
such. </div>
<div dir="auto"><br>
</div>
<div dir="auto">Great regards </div>
<div dir="auto">RedIODev </div>
</div>
<br>
<div>
<div dir="ltr">On Fri, Dec 5, 2025, 13:55 david
Grajales <<a href="mailto:david.1993grajales@gmail.com" rel="noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">david.1993grajales@gmail.com</a>>
wrote:<br>
</div>
<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<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>
<div dir="ltr">El vie, 5 dic 2025 a la(s)
6:05 a.m., Per-Ake Minborg (<a href="mailto:per-ake.minborg@oracle.com" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">per-ake.minborg@oracle.com</a>)
escribió:<br>
</div>
<blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<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_2056141226387924638m_-7781291897711540359x_m_-2042492114742708934m_-8766186915558418911m_-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_2056141226387924638m_-7781291897711540359x_m_-2042492114742708934m_-8766186915558418911m_-1330836081727153577divRplyFwdMsg" dir="ltr"> <font style="font-size:11pt" face="Calibri, sans-serif" color="#000000"><b>From:</b>
amber-dev <<a href="mailto:amber-dev-retn@openjdk.org" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">amber-dev-retn@openjdk.org</a>>
on behalf of david Grajales <<a href="mailto:david.1993grajales@gmail.com" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">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" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">amber-dev@openjdk.org</a>>;
<a href="mailto:core-libs-dev@openjdk.org" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">
core-libs-dev@openjdk.org</a>
<<a href="mailto:core-libs-dev@openjdk.org" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">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>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>
</blockquote>
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
</blockquote>
</body>
</html>