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