That's seems exactly opposite. The `get` returns initial value always making the constant initialised by calling compute. The `orElse(v)` is a shortcut for `c.isInitialized() ? c.get() : v`.
WBR, Anatoly. On Tue, 9 Dec 2025, 10:25 Maurizio Cimadamore, < [email protected]> wrote: > I agree with most of the conclusions in this thread. > > > 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). > > > Maurizio > > > > On 08/12/2025 12:31, Per-Ake Minborg wrote: > > So, it is nice that folks seem to agree that LazyConstant should only > compute and initialize its contents from the Supplier/lambda given at > declaration time. The orElse method seems to blur the contours of > LazyConstant , and so, as previously said, we might consider removing the > method altogether in the next preview. > > 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. > > Best, Per > > Confidential- Oracle Internal > ------------------------------ > *From:* David Alayachew <[email protected]> > <[email protected]> > *Sent:* Friday, December 5, 2025 2:51 PM > *To:* Red IO <[email protected]> <[email protected]> > *Cc:* david Grajales <[email protected]> > <[email protected]>; Per-Ake Minborg > <[email protected]> <[email protected]>; amber-dev > <[email protected]> <[email protected]>; core-libs-dev > <[email protected]> <[email protected]> > *Subject:* [External] : Re: Feedback about LazyConstants API (JEP526) > > Caveat -- I have only used the Java 25 version of this library. > > 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. > > Though, I'm definitely open to just removing the method. This is easy > enough to accomplish ourselves. Would prefer a rename though. > > On Fri, Dec 5, 2025, 8:32 AM Red IO <[email protected]> wrote: > > Hi David, > As par already said the orElse method doesn't initializes the > LazyConstant. > It just checks rather the value is init and if not calls the supplier to > get a substitute for the missing constant. > Example: > LazyConstant<String> x = LazyConstant.of(() -> "Const"); > var uninit1 = x.orElse(() -> "substitute 1"); > var uninit2 = x.orElse(() -> "substitute 2"); > var init1 = x.get(); > var init2 = x.orElse(() -> "substitute 3"); > uninit1 and uninit2 get the substitute 1/2 > And init1 and init2 get Const. > > This is surprising if you expect it to be a way to init it with an > alternative value. > > My suggestion would to make the separation clear and allow for another use > case by spliting this api in 2 parts: > One class LazyConstant > Takes a Supplier in static factory and exposes get() > > And > Class LazyInit > 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. > 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. > > This split makes it clear from which context the constant is initialized > from (consumer or at declaration) > > Mixing those 2 or having methods that appear to do this is rather > confusing. > > > > 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. > > My 2 suggestions here are completely independent and should be viewed as > such. > > Great regards > RedIODev > > On Fri, Dec 5, 2025, 13:55 david Grajales <[email protected]> > wrote: > > HI Per. I pleasure to talk with you. > > You are right about one thing but this actually makes the API less > intuitive and harder to read and reason about. > > LazyConstant<String> foo = LazyConstant.of(() -> "hello"); > > void main() { > if (someCondition()) {// asume false > foo.get(); > } > foo.orElse("hello2"); // ... > > println(foo.get()); // This prints "hello" > } > > But if one assigns foo.orElse("hello2") to a variable, the variable > actually gets the "hello2" value. > > void main() { > if (someCondition()) {// asume false > foo.get(); > } > var res = foo.orElse("hello2"); // ... > var res2 = foo.orElse("hello3"); > println(res); // This prints "hello2" > println(res2);//This prints "hello3" > } > > 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) > > private class Bar{ > private final LazyConstant<String> foo; > private Bar(Some some){ > > if(some.condition){ > foo = LazyConstant.of(() -> "hello"); > }else { > foo = LazyConstant.of(() -> "hello2"); > } > } > } > > Thank you for reading. This is all I have to report. > > Best regards. > > > > El vie, 5 dic 2025 a la(s) 6:05 a.m., Per-Ake Minborg ( > [email protected]) escribió: > > Hi David, > > Thank you for trying out LazyConstant and providing feedback. That is > precisely what previews are for! > > If you take a closer look at the specification of LazyConstant::orElse, it > says that the method will *never trigger initialization.* And so, you > *can* actually be sure that in your first example, foo 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 Optional works. > > It would be possible to entirely remove the orElse() method from the API, > and in the rare cases where an equivalent functionality is called for, rely > on LazyConstant::isInitialized instead. > > Best, Per > > > Confidential- Oracle Internal > ------------------------------ > *From:* amber-dev <[email protected]> on behalf of david > Grajales <[email protected]> > *Sent:* Friday, December 5, 2025 5:38 AM > *To:* amber-dev <[email protected]>; [email protected] < > [email protected]> > *Subject:* Feedback about LazyConstants API (JEP526) > > Dear Java Dev Team, > > I am writing to provide feedback and two specific observations regarding > the LazyConstant API, which is currently a preview feature in OpenJDK 26. > > 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. > > > *1. Proposal: Zero-Parameter `LazyConstant.of()` Overload:* > > 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: > > LazyConstant<String> foo = LazyConstant.of(() -> "hello"); > > the code gives the strong, immediate impression that the value is *always* > initialized to "hello". This makes it difficult to infer that the > constant might ultimately resolve to an alternative value set later via > orElse() or another conditional path, especially when skimming the code: > > LazyConstant<String> foo = LazyConstant.of(() -> "hello"); // When > skimming the code it's not always obvious that this may not be the actual > value > > void main() { > if (someCondition()) { > foo.get(); // Trigger initialization to "hello" > } > // If someCondition is false, the final value of foo is determined here: > > var res1 = foo.orElse("hello2"); // ... > } > > *My Suggestion:* I propose introducing a *zero-parameter overloaded > static factory method* of(): > > LazyConstant<String> foo = LazyConstant.of(); > > This form explicitly communicates that the constant is initialized to an * > unresolved* state, suggesting that the value will be determined > downstream by the first invocation of an initialization/computation method. > > LazyConstant<String> foo = LazyConstant.of(); // Clearly unresolved > void main() { > if (someCondition()) { > foo.orElse("hello"); > } > var res1 = foo.orElse("hello2"); // ... > } > > This is specially useful for clarity when one has conditional > initialization in places such as the constructor of a class. For example > > private class Bar{ > LazyConstant<String> foo = LazyConstant.of(); > private Bar(Some some){ > if(some.condition()){ > foo.orElse("foo"); > } > foo.orElse("foo2"); > } > > String computeValue() { > return "hello"; > } > > String computeValue2(){ > return "hello2"; > } > } > 2. Method Naming Suggestion and and supplier in instance method for > consistency in the API > > My second, much more minor observation relates to the instance method orElse(T > t). > > While orElse fits a retrieval pattern, I personally feel that * compute* > or *computeIfAbsent* would better express the intent of this method, as > its primary function is not just to retrieve, but to trigger the > computation and *set the final value* 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. > > > private class Bar{ > 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. > private Bar(Some some){ > foo.compute(some::executeCallToCacheDBAndBringInitializationParams) > //Real configuration happens here > > } > } > > This last it's very common for initialization of configuration classes and > singletons. > > > Thank you so much for your attention, I hope you find this feedback useful. > > Always yours. David Grajales > >
