写点什么

我看 JAVA 之 枚举类型

用户头像
awen
关注
发布于: 2021 年 02 月 27 日

我看 JAVA 之 枚举类型


注:基于 jdk11


Enum


Enum是Java(1.5+)中所有枚举类型的公共基类。有关枚举的更多信息,包括编译器合成的隐式声明方法的描述,可以在Java™语言规范的[第8.9节](https://docs.oracle.com/javase/specs/jls/se11/html/jls-8.html#jls-8.9)中找到。当使用枚举类型作为Set中的元素或Map中的key时,可以使用专用且高效的java.util.EnumSetjava.util.EnumMap实现。
定义一个枚举类,隐式继承了java.lang.Enum类(所以枚举类只能去实现接口不能显式继承其他类),见如下代码块:enum Color {// RED, GREEN, BLANK, YELLOW}
复制代码


实现了如下几个接口


1. Comparable2. Serializable
复制代码


源码分析:


public abstract class Enum<E extends Enum<E>>    implements Comparable<E>, Serializable {/** * accessing this field.枚举常量名称,访问名称时,最好使用toString()方法而不是直接访问name字段。 */private final String name;
/** * 枚举常量名称,访问名称时,最好使用toString()方法而不是此方法。 */public final String name() { return name;}
/** * 枚举常量在枚举类中定义的次序,次序从0开始。开发人员很少用到这个字段。此字典被设计用来在基于枚举类型的复杂数据结构中,如 java.util.EnumSet 和 java.util.EnumMap。 * */private final int ordinal;
public final int ordinal() { return ordinal;}
/** * Sole constructor. Programmers cannot invoke this constructor. * It is for use by code emitted by the compiler in response to * enum type declarations. * 唯一的构造器。开发人员不能调用这个构造函数。它由编译器调用以响应枚举类型的声明。 */protected Enum(String name, int ordinal) { this.name = name; this.ordinal = ordinal;}
/** * 默认返回枚举常量的名字,此方法可以被覆盖以便返回更加友好name。 * * @return the name of this enum constant */public String toString() { return name;}
/** * Returns true if the specified object is equal to this * enum constant. * * @param other the object to be compared for equality with this object. * @return true if the specified object is equal to this * enum constant. */public final boolean equals(Object other) { return this==other;}
public final int hashCode() { return super.hashCode();}
/** * 枚举类型不可以克隆,以保持其单例性。 * @return (never returns) */protected final Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException();}
/** * 比较算法是比较枚举常量的次序。 */public final int compareTo(E o) { Enum<?> other = (Enum<?>)o; Enum<E> self = this; if (self.getClass() != other.getClass() && // optimization self.getDeclaringClass() != other.getDeclaringClass()) throw new ClassCastException(); return self.ordinal - other.ordinal;}
/** * 返回枚举常量对应的类对象。如果两个枚举常量调用getDeclaringClass()值相等,name这两个枚举对象的枚举类型相同。 */@SuppressWarnings("unchecked")public final Class<E> getDeclaringClass() { Class<?> clazz = getClass(); Class<?> zuper = clazz.getSuperclass(); return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;}
/** * 返回指定枚举类型和名称的枚举常量。参数name一定要与指定枚举类型的常量名称相同(多余的空白字符也是不被允许的)。 */public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { T result = enumType.enumConstantDirectory().get(name); if (result != null) return result; if (name == null) throw new NullPointerException("Name is null"); throw new IllegalArgumentException( "No enum constant " + enumType.getCanonicalName() + "." + name);}
/** * 枚举类没有 finalize() */@SuppressWarnings("deprecation")protected final void finalize() { }
/** * prevent default deserialization */private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("can't deserialize enum");}
private void readObjectNoData() throws ObjectStreamException { throw new InvalidObjectException("can't deserialize enum");}}
复制代码


适用原则


枚举在什么地方适用呢?一条普遍规则是,任何使用常量的地方,例如目前用 switch 代码切换常量的地方。如果只有单独一个值(例如,鞋的最大尺寸,或者笼子中能装猴子的最大数目),则还是把这个任务留给常量吧。但是,如果定义了一组值,而这些值中的任何一个都可以用于特定的数据类型,那么将枚举用在这个地方最适合不过。
复制代码


例子:


    package chapter03;
public class TestEnum { public static void main(String [] args) { System.out.println(Color.RED); System.out.println(Color.RED.name()); System.out.println(Color.RED.ordinal()); System.out.println(Color.class); System.out.println(Color.class.isEnum());
System.out.println(Color.RED.getDeclaringClass());
System.out.println("--- Class.getEnumConstants() ---"); for (Color color: Color.RED.getClass().getEnumConstants()) { System.out.println(color); }
System.out.println("--- interface enhance ---"); System.out.println(Color.RED.info());
System.out.println("--- switch clause ---"); System.out.println(swithColor(Color.RED));
System.out.println("--- Enum.valueOf() ---"); System.out.println(Enum.valueOf(Color.class, "YELLOW")); System.out.println(Enum.valueOf(Color.class, " YELLOW")); }
public static Color swithColor(Color color) { switch (color) { case RED : return Color.GREEN; case GREEN : return Color.YELLOW; case YELLOW : return Color.RED; default: return Color.GREEN; }
} } interface ColorInterface { String info(); } enum Color implements ColorInterface{ RED, GREEN, YELLOW;
@Override public String info() { return name() + "'s info"; } }

复制代码

打印结果如下:


RED

RED

0

class chapter03.Color

true

class chapter03.Color

--- Class.getEnumConstants() ---

RED

GREEN

YELLOW

--- interface enhance ---

RED's info

--- switch clause ---

GREEN

--- Enum.valueOf() ---

YELLOW

Exception in thread "main" java.lang.IllegalArgumentException: No enum constant chapter03.Color.

at java.base/java.lang.Enum.valueOf(Enum.java:240)

at chapter03.TestEnum.main(TestEnum.java:21)


用户头像

awen

关注

Things happen for a reason. 2019.11.15 加入

还未添加个人简介

评论

发布
暂无评论
我看JAVA 之 枚举类型