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