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