src/java.base/share/classes/java/lang/Enum.java
changeset 52914 4fa75d8ad418
parent 51413 43e41800d579
child 55210 e079a4cfad75
child 58678 9cf78a70fa4f
--- a/src/java.base/share/classes/java/lang/Enum.java	Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Enum.java	Sun Dec 09 12:36:24 2018 -0500
@@ -25,11 +25,19 @@
 
 package java.lang;
 
-import java.io.Serializable;
 import java.io.IOException;
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDescs;
+import java.lang.constant.DynamicConstantDesc;
+import java.lang.invoke.MethodHandles;
+import java.util.Optional;
+
+import static java.util.Objects.requireNonNull;
 
 /**
  * This is the common base class of all Java language enumeration types.
@@ -56,7 +64,7 @@
 @SuppressWarnings("serial") // No serialVersionUID needed due to
                             // special-casing of enum types.
 public abstract class Enum<E extends Enum<E>>
-        implements Comparable<E>, Serializable {
+        implements Constable, Comparable<E>, Serializable {
     /**
      * The name of this enum constant, as declared in the enum declaration.
      * Most programmers should use the {@link #toString} method rather than
@@ -204,6 +212,21 @@
     }
 
     /**
+     * Returns an enum descriptor {@code EnumDesc} for this instance, if one can be
+     * constructed, or an empty {@link Optional} if one cannot be.
+     *
+     * @return An {@link Optional} containing the resulting nominal descriptor,
+     * or an empty {@link Optional} if one cannot be constructed.
+     * @since 12
+     */
+    @Override
+    public final Optional<EnumDesc<E>> describeConstable() {
+        return getDeclaringClass()
+                .describeConstable()
+                .map(c -> EnumDesc.of(c, name));
+    }
+
+    /**
      * Returns the enum constant of the specified enum type with the
      * specified name.  The name must match exactly an identifier used
      * to declare an enum constant in this type.  (Extraneous whitespace
@@ -258,4 +281,56 @@
     private void readObjectNoData() throws ObjectStreamException {
         throw new InvalidObjectException("can't deserialize enum");
     }
+
+    /**
+     * A <a href="package-summary.html#nominal">nominal descriptor</a> for an
+     * {@code enum} constant.
+     *
+     * @param <E> the type of the enum constant
+     *
+     * @since 12
+     */
+    public static final class EnumDesc<E extends Enum<E>>
+            extends DynamicConstantDesc<E> {
+
+        /**
+         * Constructs a nominal descriptor for the specified {@code enum} class and name.
+         *
+         * @param constantType a {@link ClassDesc} describing the {@code enum} class
+         * @param constantName the unqualified name of the enum constant
+         * @throws NullPointerException if any argument is null
+         * @jvms 4.2.2 Unqualified Names
+         */
+        private EnumDesc(ClassDesc constantType, String constantName) {
+            super(ConstantDescs.BSM_ENUM_CONSTANT, requireNonNull(constantName), requireNonNull(constantType));
+        }
+
+        /**
+         * Returns a nominal descriptor for the specified {@code enum} class and name
+         *
+         * @param <E> the type of the enum constant
+         * @param enumClass a {@link ClassDesc} describing the {@code enum} class
+         * @param constantName the unqualified name of the enum constant
+         * @return the nominal descriptor
+         * @throws NullPointerException if any argument is null
+         * @jvms 4.2.2 Unqualified Names
+         * @since 12
+         */
+        public static<E extends Enum<E>> EnumDesc<E> of(ClassDesc enumClass,
+                                                        String constantName) {
+            return new EnumDesc<>(enumClass, constantName);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public E resolveConstantDesc(MethodHandles.Lookup lookup)
+                throws ReflectiveOperationException {
+            return Enum.valueOf((Class<E>) constantType().resolveConstantDesc(lookup), constantName());
+        }
+
+        @Override
+        public String toString() {
+            return String.format("EnumDesc[%s.%s]", constantType().displayName(), constantName());
+        }
+    }
 }