- Java 中,枚举类(Enum)是一种特殊的数据类型,用于定义一组固定数量 的 常量。
- 相比传统的 常量定义方式,枚举提供了更好的类型安全性、可读性和功能扩展性。
- 如:public static final。
- 枚举类(Enum)内部的每个 枚举常量都是该 枚举类(Enum)的一个实例。
1、枚举类的基本语法
- 语法
public enum Color {
RED, GREEN, BLUE; // 枚举常量(必须放在第一行)
}
- 核心优势:类型安全、代码集中管理、编译器强制校验。
- 典型应用:状态机、策略模式、操作符差异化逻辑等场景。
package org.rainlotus.materials.javabase.a04_oop.aboutenum;
public enum HttpStatus {
OK(200) {
@Override
public String getMessage() {
return "请求成功";
}
},
NOT_FOUND(404) {
@Override
public String getMessage() {
return "资源未找到";
}
};
private final int code;
private HttpStatus(int code) {
this.code = code;
}
public int getCode() {
return code;
}
/**
* 抽象方法(每个枚举常量必须实现)
* @return
*/
public abstract String getMessage();
public static void main(String[] args) {
HttpStatus status = HttpStatus.OK;
// 输出: 200: 请求成功
System.out.println(status.getCode() + ": " + status.getMessage());
}
}
2、枚举类的特点
- 隐式 继承 java.lang.Enum。因此,不能显式继承其他类。
- 可以实现 接口。
- 枚举的构造器默认是 private,不能声明为 public 或 protected。
- 枚举实例必须在第一行显式声明,多个 实例用逗号分隔。
- 可以定义属性、方法。
3、枚举的常用方法
- 枚举类自动 继承 Enum 类,提供以下常用方法:
方法 | 说明 |
---|---|
name() | 返回枚举常量的名称(如: “RED”) |
ordinal() | 返回枚举常量的声明顺序(从 0 开始) |
values() | 返回所有枚举常量的数组。 |
valueOf(String name) | 根据名称返回对应的枚举常量 |
- 示例:
public enum Color {
// 枚举常量(必须放在第一行)
RED, GREEN, BLUE;
public static void main(String[] args) {
Color red = Color.RED;
// 返回枚举常量的名称:输出 RED
System.out.println(red.name());
// 返回枚举常量的声明顺序(从 0 开始):输出 0
System.out.println(red.ordinal());
Color[] colors = Color.values();
// 返回所有枚举常量的数组:[RED, GREEN, BLUE]
System.out.println(Arrays.toString(colors));
Color green = Color.valueOf("GREEN");
// 根据名称返回对应的枚举常量:GREEN
System.out.println(green);
}
}
4、枚举类 与 内部定义的常量 之间的关系 的 理解
- 理解:枚举类 中的 每个常量(如:RED、GREEN),本质上是该枚举类的一个个具体的实例对象。
- 这些具体实例(常量)在枚举类加载时被初始化,且全局唯一、数量固定、不可变。
- 每个实例可以携带自己的状态(属性)和行为(方法)。
public enum Color {
RED, // 相当于 new Color("RED", 0)
GREEN, // 相当于 new Color("GREEN", 1)
BLUE; // 相当于 new Color("BLUE", 2)
}
- 原理:
- 每个 枚举常量 会被 编译器 转换为类似:
- public static final Color RED = new Color(“RED”, 0); 的代码。
- 这些实例通过枚举类的 私有构造器 创建,且数量固定。
4.1、为枚举常量添加属性、自定义构造器、自定义方法:
package org.rainlotus.materials.javabase.a04_oop.aboutenum;
public enum Season {
SPRING("春天", 15),
SUMMER("夏天", 30),
AUTUMN("秋天", 20),
WINTER("冬天", 5);
private final String chineseName;
private final int temperature;
/**
* 构造器必须是 private(可省略)
* @param chineseName
* @param temperature
*/
Season(String chineseName, int temperature) {
this.chineseName = chineseName;
this.temperature = temperature;
}
/**
* 自定义方法
* @return
*/
public String getDescription() {
return chineseName + "的平均温度是:" + temperature + "℃";
}
public static void main(String[] args) {
// 使用示例
Season spring = Season.SPRING;
// 春天 的平均温度是:15℃
System.out.println(spring.getDescription());
}
}
4.2、定义 抽象方法 的 枚举类
- 在 Java 中,枚举类可以定义 抽象方法,并要求 每个枚举常量 都必须实现这个抽象方法。
- 每个枚举常量 都必须通过匿名内部类的方式实现这个抽象方法。
- 这种特性使得枚举类能够为不同的 枚举常量 定义 不同的行为,类似于多态的实现。
package org.rainlotus.materials.javabase.a04_oop.aboutenum;
/**
* @author zhangxw
*/
public enum Operation {
// 每个枚举常量 都必须通过匿名内部类的方式实现这个抽象方法。
ADD {
@Override
public int execute(int a, int b) {
return a + b;
}
},
SUBTRACT {
@Override
public int execute(int a, int b) {
return a - b;
}
},
MULTIPLY {
@Override
public int execute(int a, int b) {
return a * b;
}
},
DIVIDE {
@Override
public int execute(int a, int b) {
return a / b;
}
};
/**
* 定义抽象方法
*/
public abstract int execute(int a, int b);
public static void main(String[] args) {
int result = Operation.ADD.execute(5, 3);
// 输出:5 + 3 = 8
System.out.println("5 + 3 = " + result);
result = Operation.MULTIPLY.execute(4, 6);
// 输出:4 * 6 = 24
System.out.println("4 * 6 = " + result);
}
}
- 关键点:
- 枚举类中定义的抽象方法必须由所有 枚举常量实现。
- 每个枚举常量的实现通过匿名内部类完成。
- 枚举类末尾的分号(;)是可选的(如果只有枚举常量没有其他成员。如:没有属性)。
4.3、实现 接口 的 枚举类
- 方式一:
package org.rainlotus.materials.javabase.a04_oop.aboutenum;
public enum Orientation1 implements Directionable {
EAST("东方"),
SOUTH("南方"),
WEST("西方"),
NORTH("北方");
private final String chineseName;
private Orientation1(String chineseName) {
this.chineseName = chineseName;
}
public void pointDirection() {
System.out.println("指向:"+ this.chineseName);
}
public static void main(String[] args) {
// 指向:东方
Orientation1.EAST.pointDirection();
}
}
- 方式二:
package org.rainlotus.materials.javabase.a04_oop.aboutenum;
public enum Orientation2 implements Directionable {
EAST("东方"){
@Override
public void pointDirection() {
System.out.println("指向:" + this.getChineseName());
}
},
SOUTH("南方"){
@Override
public void pointDirection() {
System.out.println("指向:" + this.getChineseName());
}
},
WEST("西方"){
@Override
public void pointDirection() {
System.out.println("指向:" + this.getChineseName());
}
},
NORTH("北方"){
@Override
public void pointDirection() {
System.out.println("指向:" + this.getChineseName());
}
};
private final String chineseName;
Orientation2(String chineseName) {
this.chineseName = chineseName;
}
public String getChineseName() {
return chineseName;
}
public static void main(String[] args) {
// 指向:东方
Orientation2.EAST.pointDirection();
}
}
5、枚举能有那些元素?
枚举类可以有 field、方法、构造器(只能 private 修饰)、初始化块、内部类。
// public 后只能有 abstract 或 fianl 其中之一,默认是 final
public enum Gender {
// 列出所有枚举值----也就是该枚举类的所有可能的实例。
// 但实际上调用相应的构造器来创建枚举实例。
MALE("男","力气要大"), FEMALE("女");
private String name;
private String desc;
// 构造器无论是否使用 private 修饰,默认总是用 private 修饰的。
private Gender(String name) {
this.name = name;
}
private Gender(String name,String desc) {
this.desc = desc;
}
public void setName(String name) {
// this 代表调用该方法实例
switch(this){
// 要求别修改的属性,必须当前枚举实例。
case MALE:
if(name.equals("男")||name.equals("male")){
this.name = name;
} else {
System.out.println("参数错误");
}
break;
case FEMALE:
if(name.equals("女")||name.equals("female")){
this.name = name;
} else {
System.out.println("参数错误");
}
break;
}
//this.name = name;
}
{
System.out.println("初始化块");
}
public void info(){
System.out.println("info方法:"+this);
System.out.println("名称性别是:"+this.name);
}
public static void main(String[] args) {
}
class A{
}
}
public class GenderTest {
public static void main(String[] args) {
Gender male = Gender.MALE;
male.setName("男");
//System.out.println(male);
male.info();
}
}