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