优秀的编程知识分享平台

网站首页 > 技术文章 正文

从JDK角度认识枚举enum(java如何使用枚举)

nanyue 2024-08-08 19:12:14 技术文章 8 ℃

对于比较稳定的值集合,Java 提供了枚举来定义,通过它可以很方便管理集合。那么 Java 的枚举是通过怎样的机制实现的?本文将从 JDK 角度来看看枚举的原理。

定义枚举

使用很简单,比如定义一个表示“环保”、“交通”、“手机”三个值的集合,那么就可以直接定义如下,然后可直接 Labels.ENVIRONMENT 使用,

java

同时也可以使用带构造函数的枚举,如下,可以通过 getName 获取值。

java

编译器做了什么

Java

Java中的枚举的实现机制是怎样的?枚举看起来有点像上帝扔给我们的语法糖,秉着深入挖一挖的精神,看看枚举是相关实现,看看编译器做了什么。用 javap 看上面两个枚举编译后的字节码:

java

java

可以清晰地看到枚举被编译后其实就是一个类,该类被声明成 final,说明其不能被继承,同时它继承了 Enum 类。枚举里面的元素被声明成 static final ,另外生成一个静态代码块 static{},最后还会生成 values 和 valueOf 两个方法。下面以最简单的 Labels 为例,一个一个模块来看。

Enum 类

Enum 类是一个抽象类,主要有 name 和 ordinal 两个属性,分别用于表示枚举元素的名称和枚举元素的位置索引,而构造函数传入的两个变量刚好与之对应。

  • toString 方法直接返回 name。

  • equals 方法直接用 == 比较两个对象。

  • hashCode 方法调用的是父类的 hashCode 方法。

  • 枚举不支持 clone、finalize 和 readObject 方法。

  • compareTo 方法可以看到就是比较 ordinal 的大小。

  • valueOf 方法,根据传入的字符串 name 来返回对应的枚举元素。

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { private final String name; private final int ordinal; public final String name() { return name; } public final int ordinal() { return ordinal; } protected Enum(String name, int ordinal) { this.name = name; this.ordinal = ordinal; } public String toString() { return name; } public final boolean equals(Object other) { return this==other; } public final int hashCode() { return super.hashCode(); } 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() && self.getDeclaringClass() != other.getDeclaringClass()) throw new ClassCastException(); return self.ordinal - other.ordinal; } @SuppressWarnings("unchecked") public final Class<E> getDeclaringClass() { Class<?> clazz = getClass(); Class<?> zuper = clazz.getSuperclass(); return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper; } 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); } @SuppressWarnings("deprecation") protected final void finalize() { } 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"); } }
最近发表
标签列表