Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8319044

CSR JEP 463: Core Reflection API changes for Implicitly Declared Classes (Second Preview)

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 22
    • core-libs
    • None
    • source
    • minimal
    • Preview APIs are generally subject to change.
    • Java API
    • SE

      Summary

      Remove reflective APIs for unnamed classes, remove documentation related to unnamed classes from javadoc and add documentation in java.lang.Class related to implicit classes.

      Problem

      In the second preview of this feature, support for unnamed classes has been dropped and replaced with implicit classes. The distinction between unnamed classes and implicit classes is that the implicit class syntax is purely syntactic sugar and the classes generated by the compiler are exactly like regular classes with no indication of their origin.

      Solution

      Remove reflective APIs that rely on the detectability of unnamed classes and remove documentation related to unnamed classes. Also add documentation to java.lang.Class to indicate that implicit classes are a compiler construct.

      Specification

      Documentation in java.lang.Class related to unnamed classes has been replaces with documentation for implicit classes.

      java.lang.Class::isUnnamedClass is removed. This was the method used to detect an unnamed class. It is not possible to detect implicit classes since they are regular classes. java.lang.Class::getSimpleName, java.lang.Class::getCanonicalName and java.lang.Class::isAnonymousClass have documentation removed related to unnamed classes.

      diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java
      index c95aa764ee6..e1893d82901 100644
      --- a/src/java.base/share/classes/java/lang/Class.java
      +++ b/src/java.base/share/classes/java/lang/Class.java
      @@ -190,30 +190,21 @@
        * a class or interface is hidden has no bearing on the characteristics
        * exposed by the methods of class {@code Class}.
        *
      - * <h2><a id=unnamedClasses>Unnamed Classes</a></h2>
      - *
      - * 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, 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.
      + * <h2><a id=implicitClasses>Implicit Classes</a></h2>
        *
        * Conventionally, a Java compiler, starting from a source file for an
      - * unnamed class, say {@code HelloWorld.java}, creates a
      + * implicit class, say {@code HelloWorld.java}, creates a
        * similarly-named {@code class} file, {@code HelloWorld.class}, where
        * the class stored in that {@code class} file is named {@code
        * "HelloWorld"}, matching the base names of the source and {@code
        * class} files.
        *
      - * For the {@code Class} object of an unnamed class {@code
      + * For the {@code Class} object of an implicit class {@code
        * HelloWorld}, the methods to get the {@linkplain #getName name} and
        * {@linkplain #getTypeName type name} return results
        * equal to {@code "HelloWorld"}. The {@linkplain #getSimpleName
      - * simple name} of such an unnamed class is the empty string and the
      - * {@linkplain #getCanonicalName canonical name} is {@code null}.
      + * simple name} of such an implicit class is {@code "HelloWorld"} and the
      + * {@linkplain #getCanonicalName canonical name} is {@code "HelloWorld"}.
        *
        * @param <T> the type of the class modeled by this {@code Class}
        * object.  For example, the type of {@code String.class} is {@code
      @@ -1809,7 +1800,7 @@ public Class<?> getEnclosingClass() throws SecurityException {
           /**
            * 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} or {@linkplain #isUnnamedClass() unnamed}.
      +     * {@linkplain #isAnonymousClass() anonymous}.
            * A {@linkplain #isSynthetic() synthetic class}, one not present
            * in source code, can have a non-empty name including special
            * characters, such as "{@code $}".
      @@ -1822,9 +1813,6 @@ public Class<?> getEnclosingClass() throws SecurityException {
            * @since 1.5
            */
           public String getSimpleName() {
      -        if (isUnnamedClass()) {
      -            return "";
      -        }
               ReflectionData<T> rd = reflectionData();
               String simpleName = rd.simpleName;
               if (simpleName == null) {
      @@ -1874,7 +1862,6 @@ public String getTypeName() {
            * <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>
      @@ -1894,9 +1881,6 @@ public String getTypeName() {
            * @since 1.5
            */
           public String getCanonicalName() {
      -        if (isUnnamedClass()) {
      -            return null;
      -        }
               ReflectionData<T> rd = reflectionData();
               String canonicalName = rd.canonicalName;
               if (canonicalName == null) {
      @@ -1931,33 +1915,12 @@ private String getCanonicalName0() {
               }
           }
      
      <ul>
      <li>/**</li>
      <li><ul><li>{@return {@code true} if and only if the underlying class</li></ul></li>
      <li><ul><li>is an unnamed class}</li></ul></li>
      <li>*</li>
      <li><ul><li>@apiNote</li></ul></li>
      <li><ul><li>An unnamed class is not an {@linkplain #isAnonymousClass anonymous class}.</li></ul></li>
      <li>*</li>
      <li><ul><li>@since 21</li></ul></li>
      <li>*</li>
      <li><ul><li>@jls 7.3 Compilation Units</li></ul></li>
      <li>*/</li>
      <li>@PreviewFeature(feature=PreviewFeature.Feature.UNNAMED_CLASSES,</li>
      <li>reflective=true)</li>
      <li>public boolean isUnnamedClass() {</li>
      <li>return PreviewFeatures.isEnabled() &amp;&amp; isSynthetic()</li>
      <li>&amp;&amp; isTopLevelClass()</li>
      <li>&amp;&amp; Modifier.isFinal(getModifiers());
      <h2>-    }</h2></li>
      </ul>
      -
           /**
            * Returns {@code true} if and only if the underlying class
            * is an anonymous class.
            *
            * @apiNote
            * An anonymous class is not a {@linkplain #isHidden() hidden class}.
      -     * An anonymous class is not an {@linkplain #isUnnamedClass() unnamed class}.
            *
            * @return {@code true} if and only if this class is an anonymous class.
            * @since 1.5

      PDFs of changed API javadocs enclosed.

            jlaskey Jim Laskey
            jlaskey Jim Laskey
            Mandy Chung, Roger Riggs
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: