1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.lang; 28 29 import java.io.IOException; 30 import java.io.InvalidObjectException; 31 import java.io.ObjectInputStream; 32 import java.io.ObjectStreamException; 33 import java.io.Serializable; 34 import java.lang.constant.ClassDesc; 35 import java.lang.constant.Constable; 36 import java.lang.constant.ConstantDescs; 37 import java.lang.constant.DynamicConstantDesc; 38 import java.lang.invoke.MethodHandles; 39 import java.util.Optional; 40 import java.lang.reflect.InvocationTargetException; 41 import java.lang.reflect.Method; 42 import libcore.util.BasicLruCache; 43 44 import static java.util.Objects.requireNonNull; 45 46 /** 47 * This is the common base class of all Java language enumeration classes. 48 * 49 * More information about enums, including descriptions of the 50 * implicitly declared methods synthesized by the compiler, can be 51 * found in section {@jls 8.9} of <cite>The Java Language 52 * Specification</cite>. 53 * 54 * Enumeration classes are all serializable and receive special handling 55 * by the serialization mechanism. The serialized representation used 56 * for enum constants cannot be customized. Declarations of methods 57 * and fields that would otherwise interact with serialization are 58 * ignored, including {@code serialVersionUID}; see the <cite>Java 59 * Object Serialization Specification</cite> for details. 60 * 61 * <p> Note that when using an enumeration type as the type of a set 62 * or as the type of the keys in a map, specialized and efficient 63 * {@linkplain java.util.EnumSet set} and {@linkplain 64 * java.util.EnumMap map} implementations are available. 65 * 66 * @param <E> The type of the enum subclass 67 * @serial exclude 68 * @author Josh Bloch 69 * @author Neal Gafter 70 * @see Class#getEnumConstants() 71 * @see java.util.EnumSet 72 * @see java.util.EnumMap 73 * @jls 8.9 Enum Classes 74 * @jls 8.9.3 Enum Members 75 * @since 1.5 76 */ 77 @SuppressWarnings("serial") // No serialVersionUID needed due to 78 // special-casing of enum classes. 79 public abstract class Enum<E extends Enum<E>> 80 implements Constable, Comparable<E>, Serializable { 81 /** 82 * The name of this enum constant, as declared in the enum declaration. 83 * Most programmers should use the {@link #toString} method rather than 84 * accessing this field. 85 */ 86 private final String name; 87 88 /** 89 * Returns the name of this enum constant, exactly as declared in its 90 * enum declaration. 91 * 92 * <b>Most programmers should use the {@link #toString} method in 93 * preference to this one, as the toString method may return 94 * a more user-friendly name.</b> This method is designed primarily for 95 * use in specialized situations where correctness depends on getting the 96 * exact name, which will not vary from release to release. 97 * 98 * @return the name of this enum constant 99 */ name()100 public final String name() { 101 return name; 102 } 103 104 /** 105 * The ordinal of this enumeration constant (its position 106 * in the enum declaration, where the initial constant is assigned 107 * an ordinal of zero). 108 * 109 * Most programmers will have no use for this field. It is designed 110 * for use by sophisticated enum-based data structures, such as 111 * {@link java.util.EnumSet} and {@link java.util.EnumMap}. 112 */ 113 private final int ordinal; 114 115 /** 116 * Returns the ordinal of this enumeration constant (its position 117 * in its enum declaration, where the initial constant is assigned 118 * an ordinal of zero). 119 * 120 * Most programmers will have no use for this method. It is 121 * designed for use by sophisticated enum-based data structures, such 122 * as {@link java.util.EnumSet} and {@link java.util.EnumMap}. 123 * 124 * @return the ordinal of this enumeration constant 125 */ ordinal()126 public final int ordinal() { 127 return ordinal; 128 } 129 130 /** 131 * Sole constructor. Programmers cannot invoke this constructor. 132 * It is for use by code emitted by the compiler in response to 133 * enum class declarations. 134 * 135 * @param name - The name of this enum constant, which is the identifier 136 * used to declare it. 137 * @param ordinal - The ordinal of this enumeration constant (its position 138 * in the enum declaration, where the initial constant is assigned 139 * an ordinal of zero). 140 */ Enum(String name, int ordinal)141 protected Enum(String name, int ordinal) { 142 this.name = name; 143 this.ordinal = ordinal; 144 } 145 146 /** 147 * Returns the name of this enum constant, as contained in the 148 * declaration. This method may be overridden, though it typically 149 * isn't necessary or desirable. An enum class should override this 150 * method when a more "programmer-friendly" string form exists. 151 * 152 * @return the name of this enum constant 153 */ toString()154 public String toString() { 155 return name; 156 } 157 158 /** 159 * Returns true if the specified object is equal to this 160 * enum constant. 161 * 162 * @param other the object to be compared for equality with this object. 163 * @return true if the specified object is equal to this 164 * enum constant. 165 */ equals(Object other)166 public final boolean equals(Object other) { 167 return this==other; 168 } 169 170 /** 171 * Returns a hash code for this enum constant. 172 * 173 * @return a hash code for this enum constant. 174 */ hashCode()175 public final int hashCode() { 176 return super.hashCode(); 177 } 178 179 /** 180 * Throws CloneNotSupportedException. This guarantees that enums 181 * are never cloned, which is necessary to preserve their "singleton" 182 * status. 183 * 184 * @return (never returns) 185 */ clone()186 protected final Object clone() throws CloneNotSupportedException { 187 throw new CloneNotSupportedException(); 188 } 189 190 /** 191 * Compares this enum with the specified object for order. Returns a 192 * negative integer, zero, or a positive integer as this object is less 193 * than, equal to, or greater than the specified object. 194 * 195 * Enum constants are only comparable to other enum constants of the 196 * same enum type. The natural order implemented by this 197 * method is the order in which the constants are declared. 198 */ compareTo(E o)199 public final int compareTo(E o) { 200 Enum<?> other = (Enum<?>)o; 201 Enum<E> self = this; 202 if (self.getClass() != other.getClass() && // optimization 203 self.getDeclaringClass() != other.getDeclaringClass()) 204 throw new ClassCastException(); 205 return self.ordinal - other.ordinal; 206 } 207 208 /** 209 * Returns the Class object corresponding to this enum constant's 210 * enum type. Two enum constants e1 and e2 are of the 211 * same enum type if and only if 212 * e1.getDeclaringClass() == e2.getDeclaringClass(). 213 * (The value returned by this method may differ from the one returned 214 * by the {@link Object#getClass} method for enum constants with 215 * constant-specific class bodies.) 216 * 217 * @return the Class object corresponding to this enum constant's 218 * enum type 219 */ 220 @SuppressWarnings("unchecked") getDeclaringClass()221 public final Class<E> getDeclaringClass() { 222 Class<?> clazz = getClass(); 223 Class<?> zuper = clazz.getSuperclass(); 224 return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper; 225 } 226 227 /** 228 * Returns an enum descriptor {@code EnumDesc} for this instance, if one can be 229 * constructed, or an empty {@link Optional} if one cannot be. 230 * 231 * @return An {@link Optional} containing the resulting nominal descriptor, 232 * or an empty {@link Optional} if one cannot be constructed. 233 * @since 12 234 * @hide 235 */ 236 @Override describeConstable()237 public final Optional<EnumDesc<E>> describeConstable() { 238 return getDeclaringClass() 239 .describeConstable() 240 .map(c -> EnumDesc.of(c, name)); 241 } 242 243 /** 244 * Returns the enum constant of the specified enum class with the 245 * specified name. The name must match exactly an identifier used 246 * to declare an enum constant in this class. (Extraneous whitespace 247 * characters are not permitted.) 248 * 249 * <p>Note that for a particular enum class {@code T}, the 250 * implicitly declared {@code public static T valueOf(String)} 251 * method on that enum may be used instead of this method to map 252 * from a name to the corresponding enum constant. All the 253 * constants of an enum class can be obtained by calling the 254 * implicit {@code public static T[] values()} method of that 255 * class. 256 * 257 * @param <T> The enum class whose constant is to be returned 258 * @param enumClass the {@code Class} object of the enum class from which 259 * to return a constant 260 * @param name the name of the constant to return 261 * @return the enum constant of the specified enum class with the 262 * specified name 263 * @throws IllegalArgumentException if the specified enum class has 264 * no constant with the specified name, or the specified 265 * class object does not represent an enum class 266 * @throws NullPointerException if {@code enumClass} or {@code name} 267 * is null 268 * @since 1.5 269 */ 270 // BEGIN Android-changed: Use a static BasicLruCache mapping Enum class -> Enum instance array. 271 // This change was made to fix a performance regression. See b/4087759 and b/109791362 for more 272 // background information. 273 /* 274 public static <T extends Enum<T>> T valueOf(Class<T> enumClass, 275 String name) { 276 T result = enumClass.enumConstantDirectory().get(name); 277 if (result != null) 278 return result; 279 if (name == null) 280 throw new NullPointerException("Name is null"); 281 */ valueOf(Class<T> enumClass, String name)282 public static <T extends Enum<T>> T valueOf(Class<T> enumClass, 283 String name) { 284 requireNonNull(enumClass, "enumClass == null"); 285 requireNonNull(name, "name == null"); 286 T[] values = getSharedConstants(enumClass); 287 if (values == null) { 288 throw new IllegalArgumentException(enumClass.toString() + " is not an enum type."); 289 } 290 291 // Iterate backwards through the array to retain historic Android behavior in the 292 // unexpected / likely invalid case where there are multiple values with the same name. 293 for (int i = values.length - 1; i >= 0; --i) { 294 T value = values[i]; 295 if (name.equals(value.name())) { 296 return value; 297 } 298 } 299 throw new IllegalArgumentException( 300 "No enum constant " + enumClass.getCanonicalName() + "." + name); 301 } 302 enumValues(Class<? extends Enum> clazz)303 private static Object[] enumValues(Class<? extends Enum> clazz) { 304 if (!clazz.isEnum()) { 305 // Either clazz is Enum.class itself, or it is not an enum class and the method was 306 // called unsafely e.g. using an unchecked cast or via reflection. 307 return null; 308 } 309 try { 310 Method valueMethod = clazz.getDeclaredMethod("values"); 311 return (Object[]) valueMethod.invoke(null); 312 } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 313 throw new RuntimeException(e); 314 } 315 } 316 317 private static final BasicLruCache<Class<? extends Enum>, Object[]> sharedConstantsCache 318 = new BasicLruCache<Class<? extends Enum>, Object[]>(64) { 319 @Override protected Object[] create(Class<? extends Enum> enumType) { 320 return enumValues(enumType); 321 } 322 }; 323 324 /** 325 * Returns a shared, mutable array containing the constants of this enum. It 326 * is an error to modify the returned array. 327 * 328 * @hide 329 */ 330 @SuppressWarnings("unchecked") // the cache always returns the type matching enumType getSharedConstants(Class<T> enumType)331 public static <T extends Enum<T>> T[] getSharedConstants(Class<T> enumType) { 332 return (T[]) sharedConstantsCache.get(enumType); 333 } 334 // END Android-changed: Use a static BasicLruCache mapping Enum class -> Enum instance array. 335 336 /** 337 * enum classes cannot have finalize methods. 338 */ 339 @SuppressWarnings("deprecation") finalize()340 protected final void finalize() { } 341 342 /** 343 * prevent default deserialization 344 */ 345 @java.io.Serial readObject(ObjectInputStream in)346 private void readObject(ObjectInputStream in) throws IOException, 347 ClassNotFoundException { 348 throw new InvalidObjectException("can't deserialize enum"); 349 } 350 351 @java.io.Serial readObjectNoData()352 private void readObjectNoData() throws ObjectStreamException { 353 throw new InvalidObjectException("can't deserialize enum"); 354 } 355 356 // Android-changed: Hide EnumDesc API until master switches away from Android U dev. b/270028670 357 /** 358 * A <a href="{@docRoot}/java.base/java/lang/constant/package-summary.html#nominal">nominal descriptor</a> for an 359 * {@code enum} constant. 360 * 361 * @param <E> the type of the enum constant 362 * 363 * @since 12 364 * @hide 365 */ 366 public static final class EnumDesc<E extends Enum<E>> 367 extends DynamicConstantDesc<E> { 368 369 /** 370 * Constructs a nominal descriptor for the specified {@code enum} class and name. 371 * 372 * @param constantClass a {@link ClassDesc} describing the {@code enum} class 373 * @param constantName the unqualified name of the enum constant 374 * @throws NullPointerException if any argument is null 375 * @jvms 4.2.2 Unqualified Names 376 */ EnumDesc(ClassDesc constantClass, String constantName)377 private EnumDesc(ClassDesc constantClass, String constantName) { 378 super(ConstantDescs.BSM_ENUM_CONSTANT, requireNonNull(constantName), requireNonNull(constantClass)); 379 } 380 381 /** 382 * Returns a nominal descriptor for the specified {@code enum} class and name 383 * 384 * @param <E> the type of the enum constant 385 * @param enumClass a {@link ClassDesc} describing the {@code enum} class 386 * @param constantName the unqualified name of the enum constant 387 * @return the nominal descriptor 388 * @throws NullPointerException if any argument is null 389 * @jvms 4.2.2 Unqualified Names 390 * @since 12 391 */ of(ClassDesc enumClass, String constantName)392 public static<E extends Enum<E>> EnumDesc<E> of(ClassDesc enumClass, 393 String constantName) { 394 return new EnumDesc<>(enumClass, constantName); 395 } 396 397 @Override 398 @SuppressWarnings("unchecked") resolveConstantDesc(MethodHandles.Lookup lookup)399 public E resolveConstantDesc(MethodHandles.Lookup lookup) 400 throws ReflectiveOperationException { 401 return Enum.valueOf((Class<E>) constantType().resolveConstantDesc(lookup), constantName()); 402 } 403 404 @Override toString()405 public String toString() { 406 return String.format("EnumDesc[%s.%s]", constantType().displayName(), constantName()); 407 } 408 } 409 } 410