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