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