Home | History | Annotate | Download | only in lang
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
      4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      5  *
      6  * This code is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License version 2 only, as
      8  * published by the Free Software Foundation.  Oracle designates this
      9  * particular file as subject to the "Classpath" exception as provided
     10  * by Oracle in the LICENSE file that accompanied this code.
     11  *
     12  * This code is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  * version 2 for more details (a copy is included in the LICENSE file that
     16  * accompanied this code).
     17  *
     18  * You should have received a copy of the GNU General Public License version
     19  * 2 along with this work; if not, write to the Free Software Foundation,
     20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     21  *
     22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     23  * or visit www.oracle.com if you need additional information or have any
     24  * questions.
     25  */
     26 
     27 package java.lang;
     28 
     29 import java.io.Serializable;
     30 import java.io.IOException;
     31 import java.io.InvalidObjectException;
     32 import java.io.ObjectInputStream;
     33 import java.io.ObjectStreamException;
     34 import java.lang.reflect.InvocationTargetException;
     35 import java.lang.reflect.Method;
     36 import libcore.util.BasicLruCache;
     37 import libcore.util.EmptyArray;
     38 
     39 /**
     40  * This is the common base class of all Java language enumeration types.
     41  *
     42  * More information about enums, including descriptions of the
     43  * implicitly declared methods synthesized by the compiler, can be
     44  * found in section 8.9 of
     45  * <cite>The Java&trade; Language Specification</cite>.
     46  *
     47  * <p> Note that when using an enumeration type as the type of a set
     48  * or as the type of the keys in a map, specialized and efficient
     49  * {@linkplain java.util.EnumSet set} and {@linkplain
     50  * java.util.EnumMap map} implementations are available.
     51  *
     52  * @param <E> The enum type subclass
     53  * @author  Josh Bloch
     54  * @author  Neal Gafter
     55  * @see     Class#getEnumConstants()
     56  * @see     java.util.EnumSet
     57  * @see     java.util.EnumMap
     58  * @since   1.5
     59  */
     60 public abstract class Enum<E extends Enum<E>>
     61         implements Comparable<E>, Serializable {
     62     /**
     63      * The name of this enum constant, as declared in the enum declaration.
     64      * Most programmers should use the {@link #toString} method rather than
     65      * accessing this field.
     66      */
     67     private final String name;
     68 
     69     /**
     70      * Returns the name of this enum constant, exactly as declared in its
     71      * enum declaration.
     72      *
     73      * <b>Most programmers should use the {@link #toString} method in
     74      * preference to this one, as the toString method may return
     75      * a more user-friendly name.</b>  This method is designed primarily for
     76      * use in specialized situations where correctness depends on getting the
     77      * exact name, which will not vary from release to release.
     78      *
     79      * @return the name of this enum constant
     80      */
     81     public final String name() {
     82         return name;
     83     }
     84 
     85     /**
     86      * The ordinal of this enumeration constant (its position
     87      * in the enum declaration, where the initial constant is assigned
     88      * an ordinal of zero).
     89      *
     90      * Most programmers will have no use for this field.  It is designed
     91      * for use by sophisticated enum-based data structures, such as
     92      * {@link java.util.EnumSet} and {@link java.util.EnumMap}.
     93      */
     94     private final int ordinal;
     95 
     96     /**
     97      * Returns the ordinal of this enumeration constant (its position
     98      * in its enum declaration, where the initial constant is assigned
     99      * an ordinal of zero).
    100      *
    101      * Most programmers will have no use for this method.  It is
    102      * designed for use by sophisticated enum-based data structures, such
    103      * as {@link java.util.EnumSet} and {@link java.util.EnumMap}.
    104      *
    105      * @return the ordinal of this enumeration constant
    106      */
    107     public final int ordinal() {
    108         return ordinal;
    109     }
    110 
    111     /**
    112      * Sole constructor.  Programmers cannot invoke this constructor.
    113      * It is for use by code emitted by the compiler in response to
    114      * enum type declarations.
    115      *
    116      * @param name - The name of this enum constant, which is the identifier
    117      *               used to declare it.
    118      * @param ordinal - The ordinal of this enumeration constant (its position
    119      *         in the enum declaration, where the initial constant is assigned
    120      *         an ordinal of zero).
    121      */
    122     protected Enum(String name, int ordinal) {
    123         this.name = name;
    124         this.ordinal = ordinal;
    125     }
    126 
    127     /**
    128      * Returns the name of this enum constant, as contained in the
    129      * declaration.  This method may be overridden, though it typically
    130      * isn't necessary or desirable.  An enum type should override this
    131      * method when a more "programmer-friendly" string form exists.
    132      *
    133      * @return the name of this enum constant
    134      */
    135     public String toString() {
    136         return name;
    137     }
    138 
    139     /**
    140      * Returns true if the specified object is equal to this
    141      * enum constant.
    142      *
    143      * @param other the object to be compared for equality with this object.
    144      * @return  true if the specified object is equal to this
    145      *          enum constant.
    146      */
    147     public final boolean equals(Object other) {
    148         return this==other;
    149     }
    150 
    151     /**
    152      * Returns a hash code for this enum constant.
    153      *
    154      * @return a hash code for this enum constant.
    155      */
    156     public final int hashCode() {
    157         return super.hashCode();
    158     }
    159 
    160     /**
    161      * Throws CloneNotSupportedException.  This guarantees that enums
    162      * are never cloned, which is necessary to preserve their "singleton"
    163      * status.
    164      *
    165      * @return (never returns)
    166      */
    167     protected final Object clone() throws CloneNotSupportedException {
    168         throw new CloneNotSupportedException();
    169     }
    170 
    171     /**
    172      * Compares this enum with the specified object for order.  Returns a
    173      * negative integer, zero, or a positive integer as this object is less
    174      * than, equal to, or greater than the specified object.
    175      *
    176      * Enum constants are only comparable to other enum constants of the
    177      * same enum type.  The natural order implemented by this
    178      * method is the order in which the constants are declared.
    179      */
    180     public final int compareTo(E o) {
    181         Enum<?> other = (Enum<?>)o;
    182         Enum<E> self = this;
    183         if (self.getClass() != other.getClass() && // optimization
    184             self.getDeclaringClass() != other.getDeclaringClass())
    185             throw new ClassCastException();
    186         return self.ordinal - other.ordinal;
    187     }
    188 
    189     /**
    190      * Returns the Class object corresponding to this enum constant's
    191      * enum type.  Two enum constants e1 and  e2 are of the
    192      * same enum type if and only if
    193      *   e1.getDeclaringClass() == e2.getDeclaringClass().
    194      * (The value returned by this method may differ from the one returned
    195      * by the {@link Object#getClass} method for enum constants with
    196      * constant-specific class bodies.)
    197      *
    198      * @return the Class object corresponding to this enum constant's
    199      *     enum type
    200      */
    201     @SuppressWarnings("unchecked")
    202     public final Class<E> getDeclaringClass() {
    203         Class<?> clazz = getClass();
    204         Class<?> zuper = clazz.getSuperclass();
    205         return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
    206     }
    207 
    208     /**
    209      * Returns the enum constant of the specified enum type with the
    210      * specified name.  The name must match exactly an identifier used
    211      * to declare an enum constant in this type.  (Extraneous whitespace
    212      * characters are not permitted.)
    213      *
    214      * <p>Note that for a particular enum type {@code T}, the
    215      * implicitly declared {@code public static T valueOf(String)}
    216      * method on that enum may be used instead of this method to map
    217      * from a name to the corresponding enum constant.  All the
    218      * constants of an enum type can be obtained by calling the
    219      * implicit {@code public static T[] values()} method of that
    220      * type.
    221      *
    222      * @param <T> The enum type whose constant is to be returned
    223      * @param enumType the {@code Class} object of the enum type from which
    224      *      to return a constant
    225      * @param name the name of the constant to return
    226      * @return the enum constant of the specified enum type with the
    227      *      specified name
    228      * @throws IllegalArgumentException if the specified enum type has
    229      *         no constant with the specified name, or the specified
    230      *         class object does not represent an enum type
    231      * @throws NullPointerException if {@code enumType} or {@code name}
    232      *         is null
    233      * @since 1.5
    234      */
    235     public static <T extends Enum<T>> T valueOf(Class<T> enumType,
    236                                                 String name) {
    237         // Android-changed: Use a static BasicLruCache mapping Enum class -> Enum instance array.
    238         if (enumType == null) {
    239             throw new NullPointerException("enumType == null");
    240         }
    241         if (name == null) {
    242             throw new NullPointerException("name == null");
    243         }
    244         T[] values = getSharedConstants(enumType);
    245         if (values == null) {
    246             throw new IllegalArgumentException(enumType.toString() + " is not an enum type.");
    247         }
    248 
    249         // Iterate backwards through the array to retain historic Android behavior in the
    250         // unexpected / likely invalid case where there are multiple values with the same name.
    251         for (int i = values.length - 1; i >= 0; --i) {
    252             T value = values[i];
    253             if (name.equals(value.name())) {
    254                 return value;
    255             }
    256         }
    257         throw new IllegalArgumentException(
    258                 "No enum constant " + enumType.getCanonicalName() + "." + name);
    259     }
    260 
    261     private static final BasicLruCache<Class<? extends Enum>, Object[]> sharedConstantsCache
    262             = new BasicLruCache<Class<? extends Enum>, Object[]>(64) {
    263         @Override protected Object[] create(Class<? extends Enum> enumType) {
    264             if (!enumType.isEnum()) {
    265                 return null;
    266             }
    267             try {
    268                 Method method = enumType.getDeclaredMethod("values", EmptyArray.CLASS);
    269                 method.setAccessible(true);
    270                 return (Object[]) method.invoke((Object[]) null);
    271             } catch (NoSuchMethodException impossible) {
    272                 throw new AssertionError("impossible", impossible);
    273             } catch (IllegalAccessException impossible) {
    274                 throw new AssertionError("impossible", impossible);
    275             } catch (InvocationTargetException impossible) {
    276                 throw new AssertionError("impossible", impossible);
    277             }
    278         }
    279     };
    280 
    281     /**
    282      * Returns a shared, mutable array containing the constants of this enum. It
    283      * is an error to modify the returned array.
    284      *
    285      * @hide
    286      */
    287     @SuppressWarnings("unchecked") // the cache always returns the type matching enumType
    288     public static <T extends Enum<T>> T[] getSharedConstants(Class<T> enumType) {
    289         return (T[]) sharedConstantsCache.get(enumType);
    290     }
    291 
    292     /**
    293      * enum classes cannot have finalize methods.
    294      */
    295     protected final void finalize() { }
    296 
    297     /**
    298      * prevent default deserialization
    299      */
    300     private void readObject(ObjectInputStream in) throws IOException,
    301         ClassNotFoundException {
    302         throw new InvalidObjectException("can't deserialize enum");
    303     }
    304 
    305     private void readObjectNoData() throws ObjectStreamException {
    306         throw new InvalidObjectException("can't deserialize enum");
    307     }
    308 }
    309