我看JAVA 之 枚举类型

我看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. Comparable
2. 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
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)