1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2003, 2017, 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.Serializable; 30 import java.io.IOException; 31 import java.io.InvalidObjectException; 32 import java.io.ObjectInputStream; 33 import java.io.ObjectStreamException; 34 import java.lang.reflect.InvocationTargetException; 35 import java.lang.reflect.Method; 36 import java.util.Objects; 37 import libcore.util.BasicLruCache; 38 import libcore.util.EmptyArray; 39 40 /** 41 * This is the common base class of all Java language enumeration types. 42 * 43 * More information about enums, including descriptions of the 44 * implicitly declared methods synthesized by the compiler, can be 45 * found in section 8.9 of 46 * <cite>The Java™ Language Specification</cite>. 47 * 48 * <p> Note that when using an enumeration type as the type of a set 49 * or as the type of the keys in a map, specialized and efficient 50 * {@linkplain java.util.EnumSet set} and {@linkplain 51 * java.util.EnumMap map} implementations are available. 52 * 53 * @param <E> The enum type subclass 54 * @author Josh Bloch 55 * @author Neal Gafter 56 * @see Class#getEnumConstants() 57 * @see java.util.EnumSet 58 * @see java.util.EnumMap 59 * @since 1.5 60 */ 61 @SuppressWarnings("serial") // No serialVersionUID needed due to 62 // special-casing of enum types. 63 public abstract class Enum<E extends Enum<E>> 64 implements Comparable<E>, Serializable { 65 /** 66 * The name of this enum constant, as declared in the enum declaration. 67 * Most programmers should use the {@link #toString} method rather than 68 * accessing this field. 69 */ 70 private final String name; 71 72 /** 73 * Returns the name of this enum constant, exactly as declared in its 74 * enum declaration. 75 * 76 * <b>Most programmers should use the {@link #toString} method in 77 * preference to this one, as the toString method may return 78 * a more user-friendly name.</b> This method is designed primarily for 79 * use in specialized situations where correctness depends on getting the 80 * exact name, which will not vary from release to release. 81 * 82 * @return the name of this enum constant 83 */ name()84 public final String name() { 85 return name; 86 } 87 88 /** 89 * The ordinal of this enumeration constant (its position 90 * in the enum declaration, where the initial constant is assigned 91 * an ordinal of zero). 92 * 93 * Most programmers will have no use for this field. It is designed 94 * for use by sophisticated enum-based data structures, such as 95 * {@link java.util.EnumSet} and {@link java.util.EnumMap}. 96 */ 97 private final int ordinal; 98 99 /** 100 * Returns the ordinal of this enumeration constant (its position 101 * in its enum declaration, where the initial constant is assigned 102 * an ordinal of zero). 103 * 104 * Most programmers will have no use for this method. It is 105 * designed for use by sophisticated enum-based data structures, such 106 * as {@link java.util.EnumSet} and {@link java.util.EnumMap}. 107 * 108 * @return the ordinal of this enumeration constant 109 */ ordinal()110 public final int ordinal() { 111 return ordinal; 112 } 113 114 /** 115 * Sole constructor. Programmers cannot invoke this constructor. 116 * It is for use by code emitted by the compiler in response to 117 * enum type declarations. 118 * 119 * @param name - The name of this enum constant, which is the identifier 120 * used to declare it. 121 * @param ordinal - The ordinal of this enumeration constant (its position 122 * in the enum declaration, where the initial constant is assigned 123 * an ordinal of zero). 124 */ Enum(String name, int ordinal)125 protected Enum(String name, int ordinal) { 126 this.name = name; 127 this.ordinal = ordinal; 128 } 129 130 /** 131 * Returns the name of this enum constant, as contained in the 132 * declaration. This method may be overridden, though it typically 133 * isn't necessary or desirable. An enum type should override this 134 * method when a more "programmer-friendly" string form exists. 135 * 136 * @return the name of this enum constant 137 */ toString()138 public String toString() { 139 return name; 140 } 141 142 /** 143 * Returns true if the specified object is equal to this 144 * enum constant. 145 * 146 * @param other the object to be compared for equality with this object. 147 * @return true if the specified object is equal to this 148 * enum constant. 149 */ equals(Object other)150 public final boolean equals(Object other) { 151 return this==other; 152 } 153 154 /** 155 * Returns a hash code for this enum constant. 156 * 157 * @return a hash code for this enum constant. 158 */ hashCode()159 public final int hashCode() { 160 return super.hashCode(); 161 } 162 163 /** 164 * Throws CloneNotSupportedException. This guarantees that enums 165 * are never cloned, which is necessary to preserve their "singleton" 166 * status. 167 * 168 * @return (never returns) 169 */ clone()170 protected final Object clone() throws CloneNotSupportedException { 171 throw new CloneNotSupportedException(); 172 } 173 174 /** 175 * Compares this enum with the specified object for order. Returns a 176 * negative integer, zero, or a positive integer as this object is less 177 * than, equal to, or greater than the specified object. 178 * 179 * Enum constants are only comparable to other enum constants of the 180 * same enum type. The natural order implemented by this 181 * method is the order in which the constants are declared. 182 */ compareTo(E o)183 public final int compareTo(E o) { 184 Enum<?> other = (Enum<?>)o; 185 Enum<E> self = this; 186 if (self.getClass() != other.getClass() && // optimization 187 self.getDeclaringClass() != other.getDeclaringClass()) 188 throw new ClassCastException(); 189 return self.ordinal - other.ordinal; 190 } 191 192 /** 193 * Returns the Class object corresponding to this enum constant's 194 * enum type. Two enum constants e1 and e2 are of the 195 * same enum type if and only if 196 * e1.getDeclaringClass() == e2.getDeclaringClass(). 197 * (The value returned by this method may differ from the one returned 198 * by the {@link Object#getClass} method for enum constants with 199 * constant-specific class bodies.) 200 * 201 * @return the Class object corresponding to this enum constant's 202 * enum type 203 */ 204 @SuppressWarnings("unchecked") getDeclaringClass()205 public final Class<E> getDeclaringClass() { 206 Class<?> clazz = getClass(); 207 Class<?> zuper = clazz.getSuperclass(); 208 return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper; 209 } 210 211 /** 212 * Returns the enum constant of the specified enum type with the 213 * specified name. The name must match exactly an identifier used 214 * to declare an enum constant in this type. (Extraneous whitespace 215 * characters are not permitted.) 216 * 217 * <p>Note that for a particular enum type {@code T}, the 218 * implicitly declared {@code public static T valueOf(String)} 219 * method on that enum may be used instead of this method to map 220 * from a name to the corresponding enum constant. All the 221 * constants of an enum type can be obtained by calling the 222 * implicit {@code public static T[] values()} method of that 223 * type. 224 * 225 * @param <T> The enum type whose constant is to be returned 226 * @param enumType the {@code Class} object of the enum type from which 227 * to return a constant 228 * @param name the name of the constant to return 229 * @return the enum constant of the specified enum type with the 230 * specified name 231 * @throws IllegalArgumentException if the specified enum type has 232 * no constant with the specified name, or the specified 233 * class object does not represent an enum type 234 * @throws NullPointerException if {@code enumType} or {@code name} 235 * is null 236 * @since 1.5 237 */ 238 // BEGIN Android-changed: Use a static BasicLruCache mapping Enum class -> Enum instance array. 239 // This change was made to fix a performance regression. See b/4087759 and b/109791362 for more 240 // background information. valueOf(Class<T> enumType, String name)241 public static <T extends Enum<T>> T valueOf(Class<T> enumType, 242 String name) { 243 Objects.requireNonNull(enumType, "enumType == null"); 244 Objects.requireNonNull(name, "name == null"); 245 T[] values = getSharedConstants(enumType); 246 if (values == null) { 247 throw new IllegalArgumentException(enumType.toString() + " is not an enum type."); 248 } 249 250 // Iterate backwards through the array to retain historic Android behavior in the 251 // unexpected / likely invalid case where there are multiple values with the same name. 252 for (int i = values.length - 1; i >= 0; --i) { 253 T value = values[i]; 254 if (name.equals(value.name())) { 255 return value; 256 } 257 } 258 throw new IllegalArgumentException( 259 "No enum constant " + enumType.getCanonicalName() + "." + name); 260 } 261 enumValues(Class<? extends Enum> clazz)262 private static Object[] enumValues(Class<? extends Enum> clazz) { 263 if (!clazz.isEnum()) { 264 // Either clazz is Enum.class itself, or it is not an enum class and the method was 265 // called unsafely e.g. using an unchecked cast or via reflection. 266 return null; 267 } 268 try { 269 Method valueMethod = clazz.getDeclaredMethod("values"); 270 return (Object[]) valueMethod.invoke(null); 271 } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 272 throw new RuntimeException(e); 273 } 274 } 275 276 private static final BasicLruCache<Class<? extends Enum>, Object[]> sharedConstantsCache 277 = new BasicLruCache<Class<? extends Enum>, Object[]>(64) { 278 @Override protected Object[] create(Class<? extends Enum> enumType) { 279 return enumValues(enumType); 280 } 281 }; 282 283 /** 284 * Returns a shared, mutable array containing the constants of this enum. It 285 * is an error to modify the returned array. 286 * 287 * @hide 288 */ 289 @SuppressWarnings("unchecked") // the cache always returns the type matching enumType getSharedConstants(Class<T> enumType)290 public static <T extends Enum<T>> T[] getSharedConstants(Class<T> enumType) { 291 return (T[]) sharedConstantsCache.get(enumType); 292 } 293 // END Android-changed: Use a static BasicLruCache mapping Enum class -> Enum instance array. 294 295 /** 296 * enum classes cannot have finalize methods. 297 */ 298 @SuppressWarnings("deprecation") finalize()299 protected final void finalize() { } 300 301 /** 302 * prevent default deserialization 303 */ readObject(ObjectInputStream in)304 private void readObject(ObjectInputStream in) throws IOException, 305 ClassNotFoundException { 306 throw new InvalidObjectException("can't deserialize enum"); 307 } 308 readObjectNoData()309 private void readObjectNoData() throws ObjectStreamException { 310 throw new InvalidObjectException("can't deserialize enum"); 311 } 312 } 313