1 /* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package java.lang; 18 19 import java.io.Serializable; 20 import java.lang.reflect.InvocationTargetException; 21 import java.lang.reflect.Method; 22 import libcore.util.BasicLruCache; 23 import libcore.util.EmptyArray; 24 25 /** 26 * The superclass of all enumerated types. Actual enumeration types inherit from 27 * this class, but extending this class does not make a class an enumeration 28 * type, since the compiler needs to generate special information for it. 29 */ 30 public abstract class Enum<E extends Enum<E>> implements Serializable, Comparable<E> { 31 32 private static final long serialVersionUID = -4300926546619394005L; 33 34 private static final BasicLruCache<Class<? extends Enum>, Object[]> sharedConstantsCache 35 = new BasicLruCache<Class<? extends Enum>, Object[]>(64) { 36 @Override protected Object[] create(Class<? extends Enum> enumType) { 37 if (!enumType.isEnum()) { 38 return null; 39 } 40 try { 41 Method method = enumType.getDeclaredMethod("values", EmptyArray.CLASS); 42 method.setAccessible(true); 43 return (Object[]) method.invoke((Object[]) null); 44 } catch (NoSuchMethodException impossible) { 45 throw new AssertionError("impossible", impossible); 46 } catch (IllegalAccessException impossible) { 47 throw new AssertionError("impossible", impossible); 48 } catch (InvocationTargetException impossible) { 49 throw new AssertionError("impossible", impossible); 50 } 51 } 52 }; 53 54 private final String name; 55 56 private final int ordinal; 57 58 /** 59 * Constructor for constants of enum subtypes. 60 * 61 * @param name 62 * the enum constant's declared name. 63 * @param ordinal 64 * the enum constant's ordinal, which corresponds to its position 65 * in the enum declaration, starting at zero. 66 */ Enum(String name, int ordinal)67 protected Enum(String name, int ordinal) { 68 this.name = name; 69 this.ordinal = ordinal; 70 } 71 72 /** 73 * Returns the name of this enum constant. The name is the field as it 74 * appears in the {@code enum} declaration. 75 * 76 * @return the name of this enum constant. 77 * @see #toString() 78 */ name()79 public final String name() { 80 return name; 81 } 82 83 /** 84 * Returns the position of the enum constant in the declaration. The first 85 * constant has an ordinal value of zero. 86 * 87 * @return the ordinal value of this enum constant. 88 */ ordinal()89 public final int ordinal() { 90 return ordinal; 91 } 92 93 /** 94 * Returns a string containing a concise, human-readable description of this 95 * object. In this case, the enum constant's name is returned. 96 * 97 * @return a printable representation of this object. 98 */ 99 @Override toString()100 public String toString() { 101 return name; 102 } 103 104 /** 105 * Compares this object with the specified object and indicates if they are 106 * equal. In order to be equal, {@code object} must be identical to this 107 * enum constant. 108 * 109 * @param other 110 * the object to compare this enum constant with. 111 * @return {@code true} if the specified object is equal to this 112 * {@code Enum}; {@code false} otherwise. 113 */ 114 @Override equals(Object other)115 public final boolean equals(Object other) { 116 return this == other; 117 } 118 119 @Override hashCode()120 public final int hashCode() { 121 return ordinal + (name == null ? 0 : name.hashCode()); 122 } 123 124 /** 125 * {@code Enum} objects are singletons, they may not be cloned. This method 126 * always throws a {@code CloneNotSupportedException}. 127 * 128 * @return does not return. 129 * @throws CloneNotSupportedException 130 * is always thrown. 131 */ 132 @Override clone()133 protected final Object clone() throws CloneNotSupportedException { 134 throw new CloneNotSupportedException("Enums may not be cloned"); 135 } 136 137 /** 138 * Compares this object to the specified enum object to determine their 139 * relative order. This method compares the object's ordinal values, that 140 * is, their position in the enum declaration. 141 * 142 * @param o 143 * the enum object to compare this object to. 144 * @return a negative value if the ordinal value of this enum constant is 145 * less than the ordinal value of {@code o}; 0 if the ordinal 146 * values of this enum constant and {@code o} are equal; a positive 147 * value if the ordinal value of this enum constant is greater than 148 * the ordinal value of {@code o}. 149 * @see java.lang.Comparable 150 */ compareTo(E o)151 public final int compareTo(E o) { 152 return ordinal - ((Enum<?>) o).ordinal; 153 } 154 155 /** 156 * Returns the enum constant's declaring class. 157 * 158 * @return the class object representing the constant's enum type. 159 */ 160 @SuppressWarnings("unchecked") getDeclaringClass()161 public final Class<E> getDeclaringClass() { 162 Class<?> myClass = getClass(); 163 Class<?> mySuperClass = myClass.getSuperclass(); 164 if (Enum.class == mySuperClass) { 165 return (Class<E>)myClass; 166 } 167 return (Class<E>)mySuperClass; 168 } 169 170 /** 171 * Returns the constant with the specified name of the specified enum type. 172 * 173 * @param enumType 174 * the class of the enumerated type to search for the constant 175 * value. 176 * @param name 177 * the name of the constant value to find. 178 * @return the enum constant. 179 * @throws NullPointerException 180 * if either {@code enumType} or {@code name} are {@code null}. 181 * @throws IllegalArgumentException 182 * if {@code enumType} is not an enumerated type or does not 183 * have a constant value called {@code name}. 184 */ valueOf(Class<T> enumType, String name)185 public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { 186 if (enumType == null) { 187 throw new NullPointerException("enumType == null"); 188 } else if (name == null) { 189 throw new NullPointerException("name == null"); 190 } 191 T[] values = getSharedConstants(enumType); 192 if (values == null) { 193 throw new IllegalArgumentException(enumType + " is not an enum type"); 194 } 195 for (T value : values) { 196 if (name.equals(value.name())) { 197 return value; 198 } 199 } 200 throw new IllegalArgumentException(name + " is not a constant in " + enumType.getName()); 201 } 202 203 /** 204 * Returns a shared, mutable array containing the constants of this enum. It 205 * is an error to modify the returned array. 206 * 207 * @hide 208 */ 209 @SuppressWarnings("unchecked") // the cache always returns the type matching enumType getSharedConstants(Class<T> enumType)210 public static <T extends Enum<T>> T[] getSharedConstants(Class<T> enumType) { 211 return (T[]) sharedConstantsCache.get(enumType); 212 } 213 214 /** 215 * Enum types may not have finalizers. 216 * 217 * @since 1.6 218 */ 219 @Override 220 @SuppressWarnings("FinalizeDoesntCallSuperFinalize") finalize()221 protected final void finalize() { 222 } 223 } 224