Java 枚举
Java 枚举
枚举的基本定义与规范
枚举类型用于定义一个固定的枚举值列表,每个值为标识符。
定义格式
enum MyFavoriteColor{RED, BLUE, GREEN, YELLOW}
命名规范
- 枚举值:类似常量,惯例使用全部大写字母(如 RED、BLUE)
- 枚举类型:命名规则同类名,每个单词首字母大写(如 MyFavoriteColor)
变量声明
定义枚举类型后,可声明该类型变量:
MyFavoriteColor color;
枚举的核心作用与目的
- 取值限制:枚举类型的变量取值只能是预定义的枚举值或
null,不允许其他非法值 - 编译时校验:编译器在编译阶段即可拦截非法值,保证类型安全
- 对比普通变量:普通变量无法在开发阶段限制取值范围,存在非法值风险
注意:引用枚举值时,必须使用枚举类型名称作为限定词(如
MyFavoriteColor.BLUE)
用普通类模拟枚举功能
枚举的底层本质是特殊类,可通过普通类手动模拟其核心特性,需满足以下条件:
- 私有构造方法(禁止外部通过
new创建实例) - 枚举元素以公共静态常量形式定义(每个元素都是自身实例)
- 可定义公共方法或抽象方法
基础版本(含大量 if-else)
package com.sss;
/**
* @author Jing61
* 枚举类
* 构造方法私有
* 成员变量必须是static final
*/
public class WeekDay {
// 枚举元素(静态常量)
public static final WeekDay MONDAY = new WeekDay();
public static final WeekDay TUESDAY = new WeekDay();
public static final WeekDay WEDNESDAY = new WeekDay();
public static final WeekDay THURSDAY = new WeekDay();
public static final WeekDay FRIDAY = new WeekDay();
public static final WeekDay SATURDAY = new WeekDay();
public static final WeekDay SUNDAY = new WeekDay();
/**
* 私有构造方法,禁止外部new
*/
private WeekDay() {}
@Override
public String toString() {
if (this == MONDAY) return "星期一";
else if (this == TUESDAY) return "星期二";
else if (this == WEDNESDAY) return "星期三";
else if (this == THURSDAY) return "星期四";
else if (this == FRIDAY) return "星期五";
else if (this == SATURDAY) return "星期六";
else return "星期日";
}
// 返回枚举值索引(类似原生枚举的ordinal())
public int ordinal() {
if (this == MONDAY) return 0;
else if (this == TUESDAY) return 1;
else if (this == WEDNESDAY) return 2;
else if (this == THURSDAY) return 3;
else if (this == FRIDAY) return 4;
else if (this == SATURDAY) return 5;
else return 6;
}
// 返回下一天(示例方法)
public WeekDay nextDay() {
if (this == MONDAY) return TUESDAY;
else if (this == TUESDAY) return WEDNESDAY;
else if (this == WEDNESDAY) return THURSDAY;
else if (this == THURSDAY) return FRIDAY;
else if (this == FRIDAY) return SATURDAY;
else if (this == SATURDAY) return SUNDAY;
else return MONDAY;
}
}
优化版本(抽象方法 + 匿名内部类)
解决基础版本中 if-else 冗余问题,每个枚举元素独立实现抽象方法:
package com.sss;
/**
* @author Jing61
* 枚举类(抽象类版本)
* 构造方法私有
* 成员变量必须是static final
*/
public abstract class WeekDay {
// 枚举元素(匿名内部类实现抽象方法)
public static final WeekDay MONDAY = new WeekDay() {
@Override
public int ordinal() { return 0; }
@Override
public WeekDay nextDay() { return TUESDAY; }
};
public static final WeekDay TUESDAY = new WeekDay() {
@Override
public int ordinal() { return 1; }
@Override
public WeekDay nextDay() { return WEDNESDAY; }
};
public static final WeekDay WEDNESDAY = new WeekDay() {
@Override
public int ordinal() { return 2; }
@Override
public WeekDay nextDay() { return THURSDAY; }
};
public static final WeekDay THURSDAY = new WeekDay() {
@Override
public int ordinal() { return 3; }
@Override
public WeekDay nextDay() { return FRIDAY; }
};
public static final WeekDay FRIDAY = new WeekDay() {
@Override
public int ordinal() { return 4; }
@Override
public WeekDay nextDay() { return SATURDAY; }
};
public static final WeekDay SATURDAY = new WeekDay() {
@Override
public int ordinal() { return 5; }
@Override
public WeekDay nextDay() { return SUNDAY; }
};
public static final WeekDay SUNDAY = new WeekDay() {
@Override
public int ordinal() { return 6; }
@Override
public WeekDay nextDay() { return MONDAY; }
};
/**
* 私有构造方法,禁止外部new
*/
private WeekDay() {}
@Override
public String toString() {
if (this == MONDAY) return "星期一";
else if (this == TUESDAY) return "星期二";
else if (this == WEDNESDAY) return "星期三";
else if (this == THURSDAY) return "星期四";
else if (this == FRIDAY) return "星期五";
else if (this == SATURDAY) return "星期六";
else return "星期日";
}
/**
* 抽象方法:返回枚举值索引
* @return 索引值
*/
public abstract int ordinal();
/**
* 抽象方法:返回下一天
* @return 下一个星期枚举值
*/
public abstract WeekDay nextDay();
}
增强版本(含成员变量与 getter/setter)
枚举类可添加成员变量、构造方法和普通方法:
package com.sss;
/**
* @author Jing61
* 枚举类(带成员变量版本)
*/
public abstract class WeekDay {
private String name; // 成员变量
// 枚举元素(传入成员变量值)
public static final WeekDay MONDAY = new WeekDay("星期一") {
@Override
public int ordinal() { return 0; }
@Override
public WeekDay nextDay() { return TUESDAY; }
};
public static final WeekDay TUESDAY = new WeekDay("星期二") {
@Override
public int ordinal() { return 1; }
@Override
public WeekDay nextDay() { return WEDNESDAY; }
};
// 其他枚举元素(WEDNESDAY ~ SUNDAY)省略,同优化版本...
/**
* 私有构造方法(无参)
*/
private WeekDay() {}
/**
* 私有构造方法(带参数)
* @param name 星期名称
*/
private WeekDay(String name) {
this.name = name;
}
// getter/setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 其他方法(toString、ordinal、nextDay)省略,同优化版本...
}
原生枚举的使用(enum 关键字)
Java 提供 enum 关键字简化枚举定义,无需手动实现核心逻辑,原生支持多种特性。
简单枚举定义
package com.sss;
/**
* @author Jing61
* 简单枚举示例
*/
public enum MyFavoriteColor {
RED, // 枚举值(默认是public static final)
BLUE,
GREEN,
YELLOW,
ORANGE,
PURPLE,
PINK,
BROWN,
BLACK,
WHITE;
}
枚举的继承特性
- 枚举类型默认继承
java.lang.Enum类(间接继承Object) - 实现
java.lang.Comparable接口 - 继承
Object的所有方法(如toString()、equals()) - 继承
Enum的核心方法(如name()、ordinal())
枚举的核心方法
| 方法签名 | 功能说明 |
|---|---|
public String name() |
返回枚举值的名称(与定义时一致) |
public int ordinal() |
返回枚举值的序号(从 0 开始,按定义顺序递增) |
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) |
将字符串转换为对应的枚举值(名称必须完全匹配) |
public static T[] values() |
返回该枚举类型的所有值(数组形式,按定义顺序排列) |
简单枚举测试
package com.sss;
/**
* @author Jing61
* 枚举测试类
*/
public class EnumTest {
public static void main(String[] args) {
// 1. 声明枚举变量(不能通过new创建)
MyFavoriteColor color = MyFavoriteColor.BLUE;
// 2. 调用枚举方法
System.out.println(color); // 输出:BLUE(重写了toString())
System.out.println(color.name()); // 输出:BLUE(返回枚举名)
System.out.println(color.ordinal());// 输出:1(BLUE是第二个值,序号从0开始)
System.out.println(MyFavoriteColor.valueOf("BLUE")); // 输出:BLUE(字符串转枚举)
}
}
复杂枚举(带数据域、构造方法和抽象方法)
原生枚举支持添加成员变量、构造方法(默认私有)、普通方法和抽象方法。
示例:交通灯枚举
package com.sss;
/**
* 交通灯枚举(复杂枚举示例)
* @author Jing61
*/
public enum TrafficLamp {
// 枚举值:必须在最前面,带参数(对应构造方法),末尾加逗号/分号
RED(30) {
@Override
public void show() { // 实现抽象方法
System.out.println("红灯亮,禁止通行");
}
},
YELLOW(5) {
@Override
public void show() {
System.out.println("黄灯亮,准备停车");
}
},
GREEN(60) {
@Override
public void show() {
System.out.println("绿灯亮,可以通行");
}
};
// 成员变量(灯持续时间,单位:秒)
private int time;
/**
* 构造方法(默认私有,可省略private关键字)
* @param time 灯持续时间
*/
TrafficLamp(int time) {
this.time = time;
}
/**
* 普通方法:获取灯持续时间
* @return 持续时间(秒)
*/
public int getTime() {
return time;
}
/**
* 抽象方法:每个枚举值必须实现
*/
public abstract void show();
}
枚举测试
package com.sss;
/**
* 交通灯枚举测试
* @author sss
*/
public class TrafficLampTest {
public static void main(String[] args) {
// 1. 字符串转枚举
String lampName = "RED";
TrafficLamp redLamp = TrafficLamp.valueOf(lampName);
System.out.println("红灯持续时间:" + redLamp.getTime()); // 输出:30
redLamp.show(); // 输出:红灯亮,禁止通行
// 2. 遍历所有枚举值(使用values()方法)
TrafficLamp[] allLamps = TrafficLamp.values();
// foreach循环(推荐)
System.out.println("\n所有交通灯:");
for (TrafficLamp lamp : allLamps) {
System.out.print(lamp + "(" + lamp.getTime() + "秒):");
lamp.show();
}
// 普通for循环
System.out.println("\n交通灯序号与时间:");
for (int i = 0; i < allLamps.length; i++) {
TrafficLamp lamp = allLamps[i];
System.out.println("序号" + lamp.ordinal() + ":" + lamp.getName() + "," + lamp.getTime() + "秒");
}
}
}
枚举的遍历方式
foreach 循环
通过 values() 方法获取枚举数组,遍历更简洁:
for (TrafficLamp lamp : TrafficLamp.values()) {
System.out.println(lamp + ":" + lamp.getTime() + "秒");
}
普通 for 循环
TrafficLamp[] lamps = TrafficLamp.values();
for (int i = 0; i < lamps.length; i++) {
System.out.println(lamps[i].name() + ",序号:" + lamps[i].ordinal());
}

浙公网安备 33010602011771号