bye stable values, enter lazy constants
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Tue Sep 30 09:27:58 UTC 2025
Hi Sergey
>
> As you mentioned, something like LazyInitOnce might be a better name.
> Is "__Constant
> really a good alternative? Does it mainly reflect the fact that
> @Stable is used internally, and the JVM will treat the value as a
> ***true constants***? That seems more about internal JVM behavior than
> the actual semantic property of being stable.
This is a valid argument -- we'll keep fishing to see if there's better
names to express the "stability" part of the contract.
> No, I would like a solution for singletons that avoids the following
> issues:
This is a good shopping list, thanks
> - Uninitialized default value (e.g., LazyConstant.of()) - similar
> problems exist with DCL
In the new API, LazyConstant.of() is no longer present (unlike
StableValue::of), so I don't think this is an issue (e.g. you _have_ to
pass a lambda).
> - Value being created too early((e.g.,
> LazyConstant.of(Supplier<T>..))) and accessed without using the getter
> method
By "value" you mean the LazyConstant itself? Or the lambda expression
passed to the factory? Or something else?
Also, the "accessed w/o using the getter method" part: if the
initialization logic is fully provided at construction, via the lambda,
the only thing you can do to get the contents of a lazy constant is by
calling its `get` method. This is no longer like StableValue, there's no
set method. But perhaps this is the "encapsulation" problem you are
referring to -- e.g. the fact that a lazy constant field is available in
the namespace of the class (even if privately) in the first place. Let's
go back to loggers:
```
class Foo {
private static final LazyConstant<Logger> LOGGER =
LazyConstant.of(() -> makeLogger(Foo.class));
static Logger getLogger() {
return LOGGER.get();
}
}
```
The "problem" here is that you have a LOGGER field, and the
implementation of Foo can access that field directly, w/o calling
`getLogger`. Fine. But what can you do with LOGGER if not calling its
get() method (which is also what the getter does) ? I'd like to
understand the concern better here.
> - Handling exceptions more robustly than the Holder idiom
If an exception is thrown while computing the value is never set on the
lazy constant -- meaning the next call to `get` will re-generate the
same exception. With holder idiom one of the issue is that exceptions
are thrown during initialization of the holder class, which can
sometimes add confusion.
Maurizio
More information about the leyden-dev
mailing list