bye stable values, enter lazy constants

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Sep 29 19:51:19 UTC 2025


>
>>
>> But you also need another piece -- a promise that the value associated
>> with a LazyConstant changes _at most once_. That's why "Lazy", alone,
>> doesn't seem sufficient. "Lazy" just means initialized before use -- can
>> you also reassign the content? Maybe?
>
> Maybe? Do we have similar notes for records? I doubt we ever had a 
> proposal like "recordConstant" to highlight that "record" fields 
> cannot be reassigned.
>
>
>> LazyAtMostOnce would have been more precise, but I don't think it's a
>> better name :-)
>
> I have no preferences or suggestions, but if we are talking about 
> library then maybe just Lazy<T> is good enough.

The point remains: lazy doesn't imply "only one" -- so, I don't buy that 
Lazy<T> is "good enough" (although I agree it's much shorter to type -- 
which is, I think, the real argument here?)

>
>
>> Not sure about this one.
>>
>> Your code doesn't work as is -- you need at least a cast:
>>
>> ((Supplier<OrderController>)() -> new OrderController(...)).stable();
>
>
> That cast can be done through some magic, but what I want to highlight 
> is that instead of creating a new lazy-related API, we could provide 
> an API to mark an existing lazy values as "stable".

It's a possibility. But I think adding ad-hoc _language_ rules to allow 
the creation of a special supplier has a pretty terrible price vs. 
benefit ratio.

Overall it is not quite clear to me what is the main point you are 
trying to make. Once you buy this is an API and not a language feature 
(and I understand you don't fully buy that), and once you buy its name 
(as verbose as it might be), are there ways in which the proposed API 
seems insuficient?

>
> I tried reimplementing some singletons in the JDK using StableValue 
> and compared the performance. The results were great but on par with 
> the Holder idiom for cold startup as well. 
That depends on the use case -- for a single static final field, then 
yes, you move the class holder from compile-time to runtime.

When you have lots of fields, using a lazy list provides quite a big win 
compared to having separate holders (we made experiments with our 
jextract tool which demonstrate this) -- because you can have a single 
lambda/class for _all_ the elements. So you get the same performance as 
having one holder class for each element, w/o really having one holder 
for each element.

Maurizio







More information about the leyden-dev mailing list