Summary
Minor adjustments to the documentation based on PR feedback.
Problem
The LazyConstant::toString was not specified correctly. Also, the specification of the returned List/Maps' toString was incorrect.
Solution
Update the specification
https://github.com/openjdk/jdk/compare/6721ca4..e5399c5.diff
diff --git a/src/java.base/share/classes/java/lang/LazyConstant.java b/src/java.base/share/classes/java/lang/LazyConstant.java
index 5f5d37b3d1dc3..34f3d754a10f3 100644
--- a/src/java.base/share/classes/java/lang/LazyConstant.java
+++ b/src/java.base/share/classes/java/lang/LazyConstant.java
@@ -41,11 +41,11 @@
* {@linkplain LazyConstant#of(Supplier) LazyConstant.of({@code <computing function>})}.
* When created, the lazy constant is <em>not initialized</em>, meaning it has no contents.
* The lazy constant (of type {@code T}) can then be <em>initialized</em>
- * (and its contents retrieved) by calling {@linkplain #get()}. The first time
- * {@linkplain #get()} is called, the underlying <em>computing function</em>
+ * (and its contents retrieved) by calling {@linkplain #get() get()}. The first time
+ * {@linkplain #get() get()} is called, the underlying <em>computing function</em>
* (provided at construction) will be invoked and the result will be used to initialize
* the constant. Once a lazy constant is initialized, its contents can <em>never change</em>
- * and will be retrieved over and over again upon subsequent {@linkplain #get() get}
+ * and will be retrieved over and over again upon subsequent {@linkplain #get() get()}
* invocations.
* <p>
* Consider the following example where a lazy constant field "{@code logger}" holds
@@ -68,11 +68,11 @@
* <p>
* Initially, the lazy constant is <em>not initialized</em>. When {@code logger.get()}
* is first invoked, it evaluates the computing function and initializes the constant to
- * the result; the result is then returned to the client. Hence, {@linkplain #get()}
+ * the result; the result is then returned to the client. Hence, {@linkplain #get() get()}
* guarantees that the constant is <em>initialized</em> before it returns, barring
* any exceptions.
* <p>
- * Furthermore, {@linkplain #get()} guarantees that, out of several threads trying to
+ * Furthermore, {@linkplain #get() get()} guarantees that, out of several threads trying to
* invoke the computing function simultaneously, {@linkplain ##thread-safety only one is
* ever selected} for computation. This property is crucial as evaluation of the computing
* function may have side effects, for example, the call above to {@code Logger.create()}
@@ -86,10 +86,6 @@
* If the computing function recursively invokes itself (directly or indirectly via
* the lazy constant), an {@linkplain IllegalStateException} is thrown, and the lazy
* constant is not initialized.
- * <p>
- * If the computing function throws any unchecked {@linkplain Exception} or
- * {@linkplain Error}, that {@linkplain Throwable} is propagated to the caller, and the
- * lazy constant remains uninitialized.
*
* <h2 id="composition">Composing lazy constants</h2>
* A lazy constant can depend on other lazy constants, forming a dependency graph
@@ -158,8 +154,8 @@
* This is only possible if there is a direct reference from a {@code static final} field
* to a lazy constant or if there is a chain from a {@code static final} field -- via one
* or more <em>trusted fields</em> (i.e., {@code static final} fields,
- * {@linkplain Record record} fields, lazy constants, lazy lists, lazy maps,
- * or final instance fields in hidden classes) -- to a lazy constant.
+ * {@linkplain Record record} fields, or final instance fields in hidden classes) --
+ * to a lazy constant.
*
* <h2 id="miscellaneous">Miscellaneous</h2>
* Except for {@linkplain Object#equals(Object) equals(obj)} and
@@ -169,8 +165,8 @@
* @apiNote Once a lazy constant is initialized, its contents cannot ever be removed.
* This can be a source of an unintended memory leak. More specifically,
* a lazy constant {@linkplain java.lang.ref##reachability strongly references}
- * it contents. Hence, a lazy constant will hold its contents until
- * the lazy constant itself is collected (if ever).
+ * it contents. Hence, the contents of a lazy constant will be reachable as long
+ * as the lazy constant itself is reachable.
* <p>
* While it's possible to store an array inside a lazy constant, doing so will
* not result in improved access performance of the array elements. Instead, a
@@ -181,7 +177,7 @@
* <p>
* Use in static initializers may interact with class initialization order;
* cyclic initialization may result in initialization errors as described
- * in {@jls 12.4} of <cite>The Java Language Specification</cite>.
+ * in section {@jls 12.4} of <cite>The Java Language Specification</cite>.
*
* @implNote
* A lazy constant is free to synchronize on itself. Hence, care must be
@@ -206,7 +202,7 @@ public sealed interface LazyConstant<T>
permits LazyConstantImpl {
/**
- * {@return the contents of this lazy constant if initialized, otherwise,\
+ * {@return the contents of this lazy constant if initialized, otherwise,
* returns {@code other}}
* <p>
* This method never triggers initialization of this lazy constant and will observe
@@ -243,14 +239,19 @@ public sealed interface LazyConstant<T>
/**
* {@return if this lazy constant is the same as the provided {@code obj}}
- *
+ * <p>
+ * In other words, equals compares the identity of this lazy constant and {@code obj}
+ * to determine equality. Hence, two lazy constants with the same contents are
+ * <em>not</em> equal.
+ * <p>
* This method never triggers initialization of this lazy constant.
*/
@Override
boolean equals(Object obj);
/**
- * {@return the {@linkplain System#identityHashCode(Object)} for this lazy constant}
+ * {@return the {@linkplain System#identityHashCode(Object) identity hash code} for
+ * this lazy constant}
*
* This method never triggers initialization of this lazy constant.
*/
@@ -258,13 +259,14 @@ public sealed interface LazyConstant<T>
int hashCode();
/**
- * {@return a non-initializing string suitable for debugging}
+ * {@return a string suitable for debugging}
* <p>
* This method never triggers initialization of this lazy constant and will observe
* initialization by other threads atomically (i.e., it observes the
* contents if and only if the initialization has already completed).
* <p>
- * If this lazy constant is initialized, the {@linkplain Object#toString()} of the
+ * If this lazy constant is initialized, an implementation-dependent string
+ * containing the {@linkplain Object#toString()} of the
* contents will be returned; otherwise, an implementation-dependent string is
* returned that indicates this lazy constant is not yet initialized.
*/
@@ -274,18 +276,20 @@ public sealed interface LazyConstant<T>
// Factory
/**
- * {@return a lazy constant to be computed later via the provided
+ * {@return a lazy constant whose contents is to be computed later via the provided
* {@code computingFunction}}
* <p>
* The returned lazy constant strongly references the provided
- * {@code computingFunction} until initialization completes successfully; after
- * which the computing function is no longer strongly referenced and becomes
- * eligible for garbage collection.
+ * {@code computingFunction} at least until initialization completes successfully.
* <p>
* If the provided computing function is already an instance of
* {@code LazyConstant}, the method is free to return the provided computing function
* directly.
*
+ * @implNote after initialization completes successfully, the computing function is
+ * no longer strongly referenced and becomes eligible for
+ * garbage collection.
+ *
* @param computingFunction in the form of a {@linkplain Supplier} to be used
* to initialize the constant
* @param <T> type of the constant
diff --git a/src/java.base/share/classes/java/util/List.java b/src/java.base/share/classes/java/util/List.java
index 238dc34965c76..6ab80b83ef86a 100644
--- a/src/java.base/share/classes/java/util/List.java
+++ b/src/java.base/share/classes/java/util/List.java
@@ -1197,7 +1197,7 @@ static <E> List<E> copyOf(Collection<? extends E> coll) {
}
/**
- * {@return a new lazily computed list with the provided {@code size}}
+ * {@return a new lazily computed list of the provided {@code size}}
* <p>
* The returned list is an {@linkplain Collection##unmodifiable unmodifiable} list
* with the provided {@code size}. The list's elements are lazily computed via the
@@ -1207,7 +1207,7 @@ static <E> List<E> copyOf(Collection<? extends E> coll) {
* The provided computing function is guaranteed to be successfully
* invoked at most once per list index, even in a multi-threaded environment.
* Competing threads accessing an element already under computation will block until
- * an element is computed or an exception is thrown by the computing thread.
+ * an element is computed or the computing function completes abnormally
* <p>
* If invoking the provided computing function throws an exception, it is rethrown
* to the initial caller and no value for the element is recorded.
@@ -1218,8 +1218,8 @@ static <E> List<E> copyOf(Collection<? extends E> coll) {
* cannot contain {@code null} elements. Clients that want to use nullable elements
* can wrap elements into an {@linkplain Optional} holder.
* <p>
- * Any {@link List#subList(int, int) subList()} or {@link List#reversed()} views
- * of the returned list are also lazily computed.
+ * The elements of any {@link List#subList(int, int) subList()} or
+ * {@link List#reversed()} views of the returned list are also lazily computed.
* <p>
* The returned list and its {@link List#subList(int, int) subList()} or
* {@link List#reversed()} views implement the {@link RandomAccess} interface.
@@ -1228,19 +1228,22 @@ static <E> List<E> copyOf(Collection<? extends E> coll) {
* lazy list for the same index, an {@linkplain IllegalStateException}
* will be thrown.
* <p>
- * The returned list's {@linkplain Object#equals(Object) equals()} and
- * {@linkplain Object#hashCode() hashCode()} methods may trigger initialization of one
- * or more lazy elements. The returned list's {@linkplain Object#toString() toString()}
- * method never triggers initialization of elements. Instead, an
- * implementation-dependent string is returned for uninitialized elements.
+ * The returned list's {@linkplain Object Object methods};
+ * {@linkplain Object#equals(Object) equals()},
+ * {@linkplain Object#hashCode() hashCode()}, and
+ * {@linkplain Object#toString() toString()} methods may trigger initialization of
+ * one or more lazy elements.
* <p>
* The returned lazy list strongly references its computing
- * function used to compute elements only so long as there are uncomputed elements
- * after which the computing function is not strongly referenced
- * anymore and may be collected.
+ * function used to compute elements at least so long as there are uninitialized
+ * elements.
* <p>
* The returned List is <em>not</em> {@linkplain Serializable}.
*
+ * @implNote after all elements have been initialized successfully, the computing
+ * function is no longer strongly referenced and becomes eligible for
+ * garbage collection.
+ *
* @param size the size of the returned lazy list
* @param computingFunction to invoke whenever an element is first accessed
* (may not return {@code null})
diff --git a/src/java.base/share/classes/java/util/Map.java b/src/java.base/share/classes/java/util/Map.java
index eead46b9b7082..abee819069fc6 100644
--- a/src/java.base/share/classes/java/util/Map.java
+++ b/src/java.base/share/classes/java/util/Map.java
@@ -1762,7 +1762,7 @@ static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map) {
* The provided computing function is guaranteed to be successfully invoked
* at most once per key, even in a multi-threaded environment. Competing
* threads accessing a value already under computation will block until an element
- * is computed or an exception is thrown by the computing thread.
+ * is computed or the computing function completes abnormally.
* <p>
* If invoking the provided computing function throws an exception, it
* is rethrown to the initial caller and no value associated with the provided key
@@ -1774,26 +1774,29 @@ static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map) {
* cannot contain {@code null} values. Clients that want to use nullable values can
* wrap values into an {@linkplain Optional} holder.
* <p>
- * Any {@link Map#values()} or {@link Map#entrySet()} views of the returned map are
- * also lazily computed.
+ * The values of any {@link Map#values()} or {@link Map#entrySet()} views of
+ * the returned map are also lazily computed.
* <p>
* If the provided computing function recursively calls itself or
* the returned lazy map for the same key, an {@linkplain IllegalStateException}
* will be thrown.
* <p>
- * The returned map's {@linkplain Object#equals(Object) equals()} and
- * {@linkplain Object#hashCode() hashCode()} methods may trigger initialization of one
- * or more lazy values. The returned maps's {@linkplain Object#toString() toString()}
- * method never triggers initialization of values. Instead, an
- * implementation-dependent string is returned for uninitialized values.
+ * The returned map's {@linkplain Object Object methods};
+ * {@linkplain Object#equals(Object) equals()},
+ * {@linkplain Object#hashCode() hashCode()}, and
+ * {@linkplain Object#toString() toString()} methods may trigger initialization of
+ * one or more lazy elements.
* <p>
* The returned lazy map strongly references its underlying
- * computing function used to compute values only so long as there are
- * uncomputed values after which the underlying function is not strongly referenced
- * anymore and may be collected.
+ * computing function used to compute values at least so long as there are
+ * uncomputed values.
* <p>
* The returned Map is <em>not</em> {@linkplain Serializable}.
*
+ * @implNote after all values have been initialized successfully, the computing
+ * function is no longer strongly referenced and becomes eligible for
+ * garbage collection.
+ *
* @param keys the (non-null) keys in the returned computed map
* @param computingFunction to invoke whenever an associated value is first accessed
* @param <K> the type of keys maintained by the returned map
@@ -1811,7 +1814,8 @@ static <K, V> Map<K, V> ofLazy(Set<? extends K> keys,
// Also, implicit null check of `keys` and all its elements
final Set<K> keyCopies = Set.copyOf(keys);
Objects.requireNonNull(computingFunction);
- if (keys instanceof EnumSet<?> && !keys.isEmpty()) {
+ // We need to check the instance type using the original `keys` parameter.
+ if (keys instanceof EnumSet<?> && !keyCopies.isEmpty()) {
@SuppressWarnings("unchecked")
var enumMap = (Map<K, V>) LazyCollections.ofLazyMapWithEnumKeys(keyCopies, computingFunction);
return enumMap;
- csr of
-
JDK-8371882 Improve documentation for JEP 526: Lazy Constants
-
- Resolved
-