你需要关注的 Java Enum 枚举的几个细节

栏目: Java · 发布时间: 5年前

内容简介:枚举是一个非常古老的语言特性,用来实现具名的有限集合,在 C/C++ 中使用广泛。而 Java 在 Java SE5 才引入枚举。也许语言设计者觉得既然是后引入该特性,那么一定要在这个特性上支持比其他语言更多的特性。这些特性的确让 Java 的枚举功能看起来更加“成熟”,同时也引入了一些复杂性,需要开发者关注。定义一个一周七天的枚举类型:编译成 class 文件后反编译查看:

枚举是一个非常古老的语言特性,用来实现具名的有限集合,在 C/C++ 中使用广泛。而 Java 在 Java SE5 才引入枚举。也许语言设计者觉得既然是后引入该特性,那么一定要在这个特性上支持比其他语言更多的特性。这些特性的确让 Java 的枚举功能看起来更加“成熟”,同时也引入了一些复杂性,需要开发者关注。

枚举是一个不能继承的常规类

定义一个一周七天的枚举类型:

public enum EnumWeekDay {
Mon, Tue, Wed, Thu, Fri, Sat, Sun;
}
 

编译成 class 文件后反编译查看:

╰─➤  javap EnumWeekDay
Compiled from "EnumWeekDay.java"
public final class EnumWeekDay extends java.lang.Enum<enumweekday> {
public static final EnumWeekDay Mon;
public static final EnumWeekDay Tue;
public static final EnumWeekDay Wed;
public static final EnumWeekDay Thu;
public static final EnumWeekDay Fri;
public static final EnumWeekDay Sat;
public static final EnumWeekDay Sun;
public static EnumWeekDay[] values();
public static EnumWeekDay valueOf(java.lang.String);
static {};
}</enumweekday>
 
 

从反编译结果可知:

  1. 枚举类型的关键字 enum 其实只是一个语法糖,编译器最终把它转化为一个final类,因此枚举是不可继承的。
  2. 枚举类型都继承自 java.lang.Enum 类。
  3. 枚举的每一个取值被编译器传化为了一个个 static final 属性。
  4. 本质上,这就是一个普通类,因此你可以在枚举是添加各种方法,甚至是main方法。

神奇的 values() 方法

从上面我们可以看出枚举类型被添加了一个静态的 values() 方法,但是 java.lang.Enum 并没有该方法。其实,这个方法是编译器添加的。通过这个方法可以获取到该枚举类型的所有取值。这个方法在需要遍历枚举取值,进行判断筛选的场景非常有用,可参考下例的 getByZhName 方法。

在枚举中保存其他信息

在 C 中,枚举可以简单的理解为具名的整型子集。Java 扩展了这个属性,使得可以在枚举中保存其他信息。

定义一个水果枚举类,并包含中文信息:

public enum EnumFruit {
APPLE("苹果"),
BANANA("香蕉"),
ORANGE("橘子");
 
private String zhName;
 
EnumFruit(String zhName) {
System.out.println("enum init:" + zhName);
this.zhName = zhName;
}
 
/**
* Getter method for property <tt>zhName</tt>.
*
* @return property value of zhName
*/
public String getZhName() {
return zhName;
}
 
public EnumFruit getByZhName(String zhName) {
for (EnumFruit fruit : values()) {
if (fruit.getZhName().equals(zhName)) {
return fruit;
}
}
 
return null;
}
}
 
 

使用这种方式定义枚举的方式需要注意:该枚举必须含有一个构造函数,且该构造函数必须是私有的。因为枚举就是常规类,而枚举对象就是具体的枚举实例,因此枚举有多少个取值,该构造函数就会被调用多少次:

public class EnumUser {
public static void main(String[] args) {
EnumFruit fruit = EnumFruit.APPLE;
System.out.println(fruit);
}
}
 
 
enum init:苹果
enum init:香蕉
enum init:橘子
APPLE
 

使用 EnumSet 和 EnumMap 提供性能

如果要在把枚举使用在 Set、Map 等集合场景,请使用 EnumSetEnumMap 。 EnumSet 使用了 bit vector 来标记元素,EnumMap 内部将 Map 实现简化为了数组,因此可以获得更好的性能。

小结

Java 的枚举语言特性作为一个后来者,的确带来了更加“成熟”和“丰富”的实现。但是,这些丰富的特性是否一定要在日常的项目中使用,我个人是不推荐的。就我个人理解,枚举最大的优点是类型和有限集合的约束,从而增强代码的一致性。因此,我提倡在项目代码中用 C 的枚举风格来使用 Java 枚举。此外,枚举并不是编程语言必须支持的特性,比如近段时间如日中天的 Golang 是不支持枚举的。既然是一个可有可无的语言特性,那就 use is as simple as possible 吧。

扩展阅读

–EOF–


以上所述就是小编给大家介绍的《你需要关注的 Java Enum 枚举的几个细节》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

失控

失控

[美] 凯文·凯利 / 东西文库 / 新星出版社 / 2010-12 / 88.00元

《失控》,全名为《失控:机器、社会与经济的新生物学》(Out of Control: The New Biology of Machines, Social Systems, and the Economic World)。 2006年,《长尾》作者克里斯·安德森在亚马逊网站上这样评价该书: “这可能是90年代最重要的一本书”,并且是“少有的一年比一年卖得好的书”。“尽管书中的一些例子......一起来看看 《失控》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具