-
CSR
-
Resolution: Approved
-
P4
-
None
-
behavioral
-
minimal
-
Expand behavior of existing method to cover a new, preview feature.
-
Java API
-
SE
Summary
Update java.lang.Class
to describe how the names of unnamed classes are modeled in core reflection.
Problem
While the unnamed classes of JEP 445 do not have names at the source files, they are compiled to class files which do have names.
Solution
Add a general discussion of unnamed classes to the prologue of java.lang.Class
and add a predicate to determine whether or not a class is unnamed.
Specification
diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java
index 64f022c4a34..2ca95dc5a3e 100644
--- a/src/java.base/share/classes/java/lang/Class.java
+++ b/src/java.base/share/classes/java/lang/Class.java
@@ -25,6 +25,9 @@
package java.lang;
+import jdk.internal.javac.PreviewFeature;
+import jdk.internal.misc.PreviewFeatures;
+
import java.lang.annotation.Annotation;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
@@ -188,12 +191,12 @@ import sun.reflect.misc.ReflectUtil;
*
* <h2><a id=unnamedClasses>Unnamed Classes</a></h2>
*
- * A {@code class} file representing an unnamed class is generated by
+ * A {@code class} file representing an {@linkplain #isUnnamedClass unnamed class} is generated by
* a Java compiler from a source file for an unnamed class. The {@code
* Class} object representing an unnamed class is top-level,
* {@linkplain #isSynthetic synthetic}, and {@code final}. While an
* unnamed class does <em>not</em> have a name in its Java source
- * form, the various name-related methods of {@code java.lang.Class}
+ * form, several of the name-related methods of {@code java.lang.Class}
* do return non-null and non-empty results for the {@code Class}
* object representing an unnamed class.
*
@@ -205,10 +208,12 @@ import sun.reflect.misc.ReflectUtil;
* class} files.
*
* For the {@code Class} object for an unnamed class {@code
- * HelloWorld}, the methods to get the {@linkplain #getName name},
- * {@linkplain #getTypeName type name}, {@linkplain #getSimpleName
- * simple name}, and {@linkplain #getCanonicalName canonical name} all
- * return results equal to {@code "HelloWorld"}.
+ * HelloWorld}, the methods to get the {@linkplain #getName name} and
+ * {@linkplain #getTypeName type name}
+ * return results equal to {@code "HelloWorld"} while the
+ * {@linkplain #getSimpleName
+ * simple name} of such an unnamed class is the empty string and the
+ * {@linkplain #getCanonicalName canonical name} is {@code null}.
*
* @param <T> the type of the class modeled by this {@code Class}
* object. For example, the type of {@code String.class} is {@code
@@ -1742,7 +1747,7 @@ public final class Class<T> implements java.io.Serializable,
/**
* Returns the simple name of the underlying class as given in the
* source code. An empty string is returned if the underlying class is
- * {@linkplain #isAnonymousClass() anonymous}.
+ * {@linkplain #isAnonymousClass() anonymous} or {@linkplain #isUnnamedClass() unnamed}.
* A {@linkplain #isSynthetic() synthetic class}, one not present
* in source code, can have a non-empty name including special
* characters, such as "{@code $}".
@@ -1755,6 +1760,9 @@ public final class Class<T> implements java.io.Serializable,
* @since 1.5
*/
public String getSimpleName() {
+ if (isUnnamedClass()) {
+ return "";
+ }
ReflectionData<T> rd = reflectionData();
String simpleName = rd.simpleName;
if (simpleName == null) {
@@ -1804,6 +1812,7 @@ public final class Class<T> implements java.io.Serializable,
* <ul>
* <li>a {@linkplain #isLocalClass() local class}
* <li>a {@linkplain #isAnonymousClass() anonymous class}
+ * <li>an {@linkplain #isUnnamedClass() unnamed class}
* <li>a {@linkplain #isHidden() hidden class}
* <li>an array whose component type does not have a canonical name</li>
* </ul>
@@ -1823,6 +1832,9 @@ public final class Class<T> implements java.io.Serializable,
* @since 1.5
*/
public String getCanonicalName() {
+ if (isUnnamedClass()) {
+ return null;
+ }
ReflectionData<T> rd = reflectionData();
String canonicalName = rd.canonicalName;
if (canonicalName == null) {
@@ -1857,12 +1869,29 @@ public final class Class<T> implements java.io.Serializable,
}
}
+ /**
+ * {@return {@code true} if and only if the underlying class
+ * is an unnamed class}
+ *
+ * @apiNote
+ * An unnamed class is not an {@linkplain #isAnonymousClass anonymous class}.
+ *
+ * @since 21
+ */
+ @PreviewFeature(feature=PreviewFeature.Feature.UNNAMED, // change to UNNAMED_CLASSES
+ reflective=true)
+ public boolean isUnnamedClass() {
+ return isSynthetic() && PreviewFeatures.isEnabled() && isTopLevelClass();
+ }
+
+
/**
- csr of
-
JDK-8308913 Update core reflection for JEP 445 (preview)
-
- Resolved
-