public abstract class ScopedLocal<T>
extends Object
A thread-scoped value holder that abstracts over ThreadLocal
(JDK < 25) and java.lang.ScopedValue (JDK 25+),
presenting a unified API modelled after ScopedValue.
On JDK 25+, where finalized java.lang.ScopedValue is
available, this class delegates to the ScopedValue API.
On earlier JDK versions it falls back to a conventional
ThreadLocal with save-and-restore semantics.
The API mirrors the main ScopedValue operations:
private static final ScopedLocal<String> REQUEST_ID =
ScopedLocal.newInstance();
ScopedLocal.where(REQUEST_ID, "req-42").run(() -> {
assert "req-42".equals(REQUEST_ID.get());
);
ScopedLocal.where(REQUEST_ID, "req-1")
.where(TENANT_ID, "acme")
.call(() -> handleRequest());
String result = REQUEST_ID.where("req-7", () -> process());
private static final ScopedLocal CTX =
ScopedLocal.withInitial(MyCtx::new);
}
T - the type of the scoped value| Modifiers | Name | Description |
|---|---|---|
static class |
ScopedLocal.Carrier |
An immutable set of scoped-local bindings that can be applied atomically for the duration of a Runnable or Supplier. |
| Type Params | Return Type | Name and description |
|---|---|---|
|
public abstract T |
get()Returns the value bound to this scoped-local on the current thread. |
|
public abstract boolean |
isBound()Returns true if an explicit binding is active or
an initial supplier is configured. |
<T> |
public static ScopedLocal<T> |
newInstance()Creates a new ScopedLocal with no initial value. |
|
public abstract T |
orElse(T other)Returns the value bound to this scoped-local, or other
if no binding is active and no initial supplier is configured. |
<X extends Throwable> |
public abstract T |
orElseThrow(Supplier<? extends X> exceptionSupplier)Returns the value bound to this scoped-local if available, otherwise throws an exception produced by the exceptionSupplier. |
<T> |
public static ScopedLocal.Carrier |
where(ScopedLocal<T> key, T value)Creates a Carrier that binds key to value.
|
<R> |
public final R |
where(T value, Supplier<R> supplier)Binds this scoped-local to value for the duration of
the supplier, then restores the previous binding. |
|
public final void |
where(T value, Runnable action)Binds this scoped-local to value for the duration of
the action, then restores the previous binding. |
<T> |
public static ScopedLocal<T> |
withInitial(Supplier<? extends T> initialSupplier)Creates a new ScopedLocal whose get() method
returns a lazily initialized default when no explicit binding exists.
|
Returns the value bound to this scoped-local on the current thread.
Returns true if an explicit binding is active or
an initial supplier is configured.
Creates a new ScopedLocal with no initial value.
T - the value type Returns the value bound to this scoped-local, or other
if no binding is active and no initial supplier is configured.
other - the fallback valueother Returns the value bound to this scoped-local if available, otherwise throws
an exception produced by the exceptionSupplier.
If an initial supplier is configured (via withInitial(Supplier)), this method returns the initial value rather than throwing.
exceptionSupplier is nullX - the type of the exception to throw if not boundexceptionSupplier - a supplier that produces the exception to throw;
must not be null Creates a Carrier that binds key to value.
The binding takes effect when Carrier#run(Runnable)#run(Runnable) or
Carrier#call(Supplier)#call(Supplier) is invoked.
T - the value typekey - the scoped-local to bindvalue - the value to bind; may be null Binds this scoped-local to value for the duration of
the supplier, then restores the previous binding.
R - the result typevalue - the value to bind; may be nullsupplier - the action to execute with the binding active Binds this scoped-local to value for the duration of
the action, then restores the previous binding.
value - the value to bind; may be nullaction - the action to execute with the binding active Creates a new ScopedLocal whose get() method
returns a lazily initialized default when no explicit binding exists.
The supplier is invoked at most once per thread and the result is cached,
analogous to ThreadLocal.withInitial.
T - the value typeinitialSupplier - supplies the default value