Home | History | Annotate | Download | only in lang
      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