枚举是 Java 中的一种特别类型,它用于表明一组固定值。枚举中界说的每个值称为一个枚举常量,它们在声明时都必须赋予一个固定的值,即枚举值。相比于运用常量或许 final 字段来表明一组固定值,枚举更加类型安全、易读、易维护。
Java 中的枚举类型是经过关键字 enum 来界说的。一个简略的示例代码如下:
public enum WeekDay {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
这个示例代码界说了一个 WeekDay 枚举类型,其间包含了一周中的七个枚举常量。需求注意的是,枚举常量称号一般运用大写字母,这是一种约定俗成的标准。
在运用枚举类型时,可以直接运用枚举常量来表明对应的值。例如,可以界说一个办法来判别指定的日期是不是工作日:
public class Util {
public static boolean isWorkday(WeekDay day) {
switch (day) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
return true;
default:
return false;
}
}
}
在这个示例代码中,isWorkday() 办法接受一个 WeekDay 枚举常量作为参数,根据该参数判别当时日期是否是工作日。因为 WeekDay 中的枚举常量是固定不变的,因而这种方式可以有效避免传入无效的值或许字符串拼写错误等问题。
除了界说简略的枚举类型之外,Java 中的枚举还支撑许多高档特性。
枚举结构函数和字段
每个枚举常量都实际上是一个枚举实例,因而可以界说结构函数来初始化它们的状况。枚举结构函数只能是 private 或许 package-private(默许拜访权限),这是因为枚举常量的创立只能在枚举类内部进行。
例如,可以在 WeekDay 枚举中增加一个字段用于表明每个工作日的工作时间长度:
public enum WeekDay {
MONDAY(8), TUESDAY(8), WEDNESDAY(8), THURSDAY(8), FRIDAY(8),
SATURDAY(0), SUNDAY(0);
private final int workHours;
private WeekDay(int workHours) {
this.workHours = workHours;
}
public int getWorkHours() {
return workHours;
}
}
在这个示例代码中,WeekDay 枚举界说了一个 workHours 字段,用于表明每个工作日的工作时间长度。经过增加一个结构函数,可以将每个枚举常量的工作时间长度初始化为对应的值。
枚举完成接口
Java 中的枚举还可以完成一个或多个接口,这使得枚举常量可以像一般类相同具有办法和行为。例如,可以界说一个接口来表明一种颜色,然后让枚举常量完成该接口:
public interface Color {
String getName();
}
public enum Rainbow implements Color {
RED("红"), ORANGE("橙"), YELLOW("黄"), GREEN("绿"),
CYAN("青"), BLUE("蓝"), PURPLE("紫");
private final String name;
private Rainbow(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
在这个示例代码中,Rainbow 枚举完成了一个 Color 接口,该接口界说了 getName() 办法。经过完成该接口,Rainbow 枚举常量可以返回对应颜色的称号。
枚举的比较和排序
枚举常量之间的比较可以运用 “== “运算符,这是因为每个枚举常量实际上都是一个独立的对象。例如,判别两个枚举常量是否持平可以运用以下句子:
if (day == WeekDay.MONDAY) { ... }
枚举类型还支撑比较操作,包含 equals() 办法和 compareTo() 办法。默许情况下,枚举常量的比较次序是它们在枚举中的声明次序,也可以经过完成 Comparable 接口来自界说枚举常量的比较方式。
例如,可以对 WeekDay 枚举完成 Comparable 接口,按照工作日的次序进行排序:
public enum WeekDay implements Comparable<WeekDay> {
MONDAY(8), TUESDAY(8), WEDNESDAY(8), THURSDAY(8), FRIDAY(8),
SATURDAY(0), SUNDAY(0);
...
@Override
public int compareTo(WeekDay other) {
return Integer.compare(this.workHours, other.workHours);
}
}
在这个示例代码中,WeekDay 枚举完成了 Comparable 接口,重写了 compareTo() 办法,按照每个工作日的工作时间长度进行比较。经过在 compareTo() 办法中调用 Integer.compare() 办法,完成了按照整数值进行比较。
枚举的序列化和反序列化
Java 中的枚举类型可以进行序列化和反序列化,如在网络传输或保存到文件中。因为枚举常量在一个程序中是固定不变的,因而只需求序列化枚举常量的称号即可。
例如,可以运用 ObjectOutputStream 将 WeekDay 枚举序列化到文件中:
try (ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("weekdays.bin"))) {
out.writeObject(WeekDay.MONDAY);
} catch (IOException ex) {
ex.printStackTrace();
}
在反序列化时,可以运用 ObjectInputStream 读取枚举常量的称号,并经过 Enum.valueOf() 办法将其转化为对应的枚举常量:
try (ObjectInputStream in = new ObjectInputStream(
new FileInputStream("weekdays.bin"))) {
WeekDay day = WeekDay.valueOf(in.readUTF());
System.out.println(day);
} catch (IOException | ClassNotFoundException ex) {
ex.printStackTrace();
}
在这个示例代码中,先运用 readUTF() 办法读取序列化后的枚举常量称号(这里是 “MONDAY”),然后经过 valueOf() 办法将其转化为 WeekDay 枚举常量。
代码示例
颜色枚举
public enum Color {
RED("#FF0000"), GREEN("#00FF00"), BLUE("#0000FF");
private final String code;
private Color(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
这个示例代码界说了一个简略的 Color 枚举类型,其间包含三个颜色常量,每个常量都有一个对应的颜色代码。在运用时可以运用 Color.RED.getCode() 来获取赤色的颜色代码。
状况枚举
public enum Status {
NEW("新建"), OPEN("已开启"), CLOSED("已封闭");
private final String desc;
private Status(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
}
这个示例代码界说了一个简略的 Status 枚举类型,其间包含三个状况常量,每个常量都有一个对应的状况描绘。在运用时可以运用 Status.NEW.getDesc() 来获取新建状况的描绘。
星期枚举
public enum WeekDay {
MONDAY(8), TUESDAY(8), WEDNESDAY(8), THURSDAY(8), FRIDAY(8),
SATURDAY(0), SUNDAY(0);
private final int workHours;
private WeekDay(int workHours) {
this.workHours = workHours;
}
public int getWorkHours() {
return workHours;
}
public static boolean isWorkday(WeekDay day) {
return day != SATURDAY && day != SUNDAY;
}
}
这个示例代码界说了一个 WeekDay 枚举类型,其间包含七个常量,前五个为工作日,后两个为非工作日。每个工作日都有一个对应的工作时间长度,在 isWorkday() 办法中判别一个指定的日期是否为工作日。
时节枚举
public enum Season {
SPRING("春", 1), SUMMER("夏", 2), AUTUMN("秋", 3), WINTER("冬", 4);
private final String name;
private final int index;
private Season(String name, int index) {
this.name = name;
this.index = index;
}
public String getName() {
return name;
}
public int getIndex() {
return index;
}
public static Season getByIndex(int index) {
for (Season season : values()) {
if (season.getIndex() == index) {
return season;
}
}
throw new IllegalArgumentException("Invalid index: " + index);
}
}
这个示例代码界说了一个 Season 枚举类型,其间包含四个时节常量,每个常量都有一个对应的称号和索引。经过 getByIndex() 办法可以根据索引获取对应的时节枚举值。
交通信号灯枚举
public enum TrafficLight {
RED(30), GREEN(60), YELLOW(5);
private final int seconds;
private TrafficLight(int seconds) {
this.seconds = seconds;
}
public int getSeconds() {
return seconds;
}
public TrafficLight next() {
switch (this) {
case RED:
return GREEN;
case GREEN:
return YELLOW;
case YELLOW:
return RED;
default:
throw new IllegalStateException("Invalid state");
}
}
@Override
public String toString() {
return name() + "(" + seconds + ")";
}
}
这个示例代码界说了一个 TrafficLight 枚举类型,其间包含三个常量,别离表明红、绿、黄三种交通信号灯。该枚举完成了 next() 办法,返回下一个状况,以及 toString() 办法,返回对应的信号灯称号和持续时间。在运用时可以运用 TrafficLight.RED.getSeconds() 来获取红灯的持续时间。
总结
枚举类型是 Java 中的一种特别类型,它用于表明一组固定值。Java 枚举类型具有以下长处:
- 类型安全:枚举类型可以避免传入无效的值或许字符串拼写错误等问题。
- 易读易维护:经过选用命名约定和语义约定,使得代码更加可读、易于理解和维护。
- 扩展性:枚举类型支撑界说办法、字段、接口等高档特性,使得枚举常量可以像一般类相同具有行为和状况。
Java 枚举类型的运用场景包含但不限于:
- 状况码、状况标识等一组固定值的表明。
- 星期、月份、时节等一组固定值的表明。
- 颜色、性别、血型等一组固定取值的表明。
- 开关、状况机、状况转化等复杂事务逻辑的建模。
总之,在选择运用枚举类型时需求考虑其表达意义的稳定性和清晰度,以及代码的可读性和可维护性。