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.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