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 17package java.lang; 18 19import java.io.Serializable; 20import java.lang.reflect.InvocationTargetException; 21import java.lang.reflect.Method; 22import libcore.util.BasicLruCache; 23import 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 */ 30public 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 return (Object[]) method.invoke((Object[]) null); 43 } catch (NoSuchMethodException impossible) { 44 throw new AssertionError("impossible", impossible); 45 } catch (IllegalAccessException impossible) { 46 throw new AssertionError("impossible", impossible); 47 } catch (InvocationTargetException impossible) { 48 throw new AssertionError("impossible", impossible); 49 } 50 } 51 }; 52 53 private final String name; 54 55 private final int ordinal; 56 57 /** 58 * Constructor for constants of enum subtypes. 59 * 60 * @param name 61 * the enum constant's declared name. 62 * @param ordinal 63 * the enum constant's ordinal, which corresponds to its position 64 * in the enum declaration, starting at zero. 65 */ 66 protected Enum(String name, int ordinal) { 67 this.name = name; 68 this.ordinal = ordinal; 69 } 70 71 /** 72 * Returns the name of this enum constant. The name is the field as it 73 * appears in the {@code enum} declaration. 74 * 75 * @return the name of this enum constant. 76 * @see #toString() 77 */ 78 public final String name() { 79 return name; 80 } 81 82 /** 83 * Returns the position of the enum constant in the declaration. The first 84 * constant has an ordinal value of zero. 85 * 86 * @return the ordinal value of this enum constant. 87 */ 88 public final int ordinal() { 89 return ordinal; 90 } 91 92 /** 93 * Returns a string containing a concise, human-readable description of this 94 * object. In this case, the enum constant's name is returned. 95 * 96 * @return a printable representation of this object. 97 */ 98 @Override 99 public String toString() { 100 return name; 101 } 102 103 /** 104 * Compares this object with the specified object and indicates if they are 105 * equal. In order to be equal, {@code object} must be identical to this 106 * enum constant. 107 * 108 * @param other 109 * the object to compare this enum constant with. 110 * @return {@code true} if the specified object is equal to this 111 * {@code Enum}; {@code false} otherwise. 112 */ 113 @Override 114 public final boolean equals(Object other) { 115 return this == other; 116 } 117 118 @Override 119 public final int hashCode() { 120 return ordinal + (name == null ? 0 : name.hashCode()); 121 } 122 123 /** 124 * {@code Enum} objects are singletons, they may not be cloned. This method 125 * always throws a {@code CloneNotSupportedException}. 126 * 127 * @return does not return. 128 * @throws CloneNotSupportedException 129 * is always thrown. 130 */ 131 @Override 132 protected final Object clone() throws CloneNotSupportedException { 133 throw new CloneNotSupportedException("Enums may not be cloned"); 134 } 135 136 /** 137 * Compares this object to the specified enum object to determine their 138 * relative order. This method compares the object's ordinal values, that 139 * is, their position in the enum declaration. 140 * 141 * @param o 142 * the enum object to compare this object to. 143 * @return a negative value if the ordinal value of this enum constant is 144 * less than the ordinal value of {@code o}; 0 if the ordinal 145 * values of this enum constant and {@code o} are equal; a positive 146 * value if the ordinal value of this enum constant is greater than 147 * the ordinal value of {@code o}. 148 * @see java.lang.Comparable 149 */ 150 public final int compareTo(E o) { 151 return ordinal - o.ordinal; 152 } 153 154 /** 155 * Returns the enum constant's declaring class. 156 * 157 * @return the class object representing the constant's enum type. 158 */ 159 @SuppressWarnings("unchecked") 160 public final Class<E> getDeclaringClass() { 161 Class<?> myClass = getClass(); 162 Class<?> mySuperClass = myClass.getSuperclass(); 163 if (Enum.class == mySuperClass) { 164 return (Class<E>)myClass; 165 } 166 return (Class<E>)mySuperClass; 167 } 168 169 /** 170 * Returns the constant with the specified name of the specified enum type. 171 * 172 * @param enumType 173 * the class of the enumerated type to search for the constant 174 * value. 175 * @param name 176 * the name of the constant value to find. 177 * @return the enum constant. 178 * @throws NullPointerException 179 * if either {@code enumType} or {@code name} are {@code null}. 180 * @throws IllegalArgumentException 181 * if {@code enumType} is not an enumerated type or does not 182 * have a constant value called {@code name}. 183 */ 184 public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { 185 if (enumType == null) { 186 throw new NullPointerException("enumType == null"); 187 } else if (name == null) { 188 throw new NullPointerException("name == null"); 189 } 190 T[] values = getSharedConstants(enumType); 191 if (values == null) { 192 throw new IllegalArgumentException(enumType + " is not an enum type"); 193 } 194 for (T value : values) { 195 if (name.equals(value.name())) { 196 return value; 197 } 198 } 199 throw new IllegalArgumentException(name + " is not a constant in " + enumType.getName()); 200 } 201 202 /** 203 * Returns a shared, mutable array containing the constants of this enum. It 204 * is an error to modify the returned array. 205 * 206 * @hide 207 */ 208 @SuppressWarnings("unchecked") // the cache always returns the type matching enumType 209 public static <T extends Enum<T>> T[] getSharedConstants(Class<T> enumType) { 210 return (T[]) sharedConstantsCache.get(enumType); 211 } 212 213 /** 214 * Enum types may not have finalizers. 215 * 216 * @since 1.6 217 */ 218 @Override 219 @SuppressWarnings("FinalizeDoesntCallSuperFinalize") 220 protected final void finalize() { 221 } 222} 223