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