枚举_Java学习笔记

枚举是一种定义固定常量集合的类
它让代码更严谨、更安全、更优雅
并且每个枚举项都是一个对象
可以有自己的属性和方法

一、为什么会有枚举?

问题背景:

假设你要表示四个季节:

春、夏、秋、冬

最早的时候,大家可能这么写:

class Season {
    int SPRING = 1;
    int SUMMER = 2;
    int AUTUMN = 3;
    int WINTER = 4;
}

这样当然能用,但问题是:

  • 使用者不知道应该传什么值。
  • 写错也不会报错,比如 useSeason(10); 编译器不会警告。
  • 代码提示不友好(输入参数只显示“int”)。

所以后来人们用上了 常量 + static final

class Season {
    public static final int SPRING = 1;
    public static final int SUMMER = 2;
    public static final int AUTUMN = 3;
    public static final int WINTER = 4;
}

这样做虽然可以标记出不同的季节,但有两个明显的弊端

1.入参不严谨:

比如你写了一个方法:

public static void useSeason(int season) {
    switch (season) {
        case 1: System.out.println("春季"); break;
        case 2: System.out.println("夏季"); break;
        case 3: System.out.println("秋季"); break;
        case 4: System.out.println("冬季"); break;
    }
}

调用时别人可能这样传:

useSeason(5); // 没有错误,但5是什么季节??

这个值完全错误,但编译器不会报错,这就是入参不严谨的问题。

2.提示性不强:

  • IDE 只知道这个参数是 int 类型,没有任何提示到底该传 1、2、3、还是 4。
  • 比如在 IntelliJ 或 Eclipse 中写 useSeason( 时,不会有智能提示。

于是 —— 枚举(enum) 出场了!

二、什么是枚举?

枚举是一种特殊的“类”,用来表示有限且固定的一组常量
比如:

  • 季节,只有春夏秋冬
  • 性别,只有男和女
  • 订单状态,只有“已支付”“未支付”“已发货”“已完成”

定义如下:

enum Season {
    SPRING, SUMMER, AUTUMN, WINTER;
}

实际上,枚举做了两件事:

  1. 定义了一个类 Season
  2. 在这个类中自动创建了四个对象:SPRING, SUMMER, AUTUMN, WINTER

你可以理解为:

class Season {
    public static final Season SPRING = new Season();
    public static final Season SUMMER = new Season();
    public static final Season AUTUMN = new Season();
    public static final Season WINTER = new Season();

    private Season() {} // 构造器是私有的,防止别人随便创建新对象
}

是不是感觉很像常量?
但比常量更强的是:它限定类型。比如:

public static void useSeason(Season season) { ... }

现在这个方法只能传入 Season 枚举类型的值,
如果你写 useSeason(1),编译器直接报错。

  • 只能传入 Season 类型的对象;
  • IDE 自动提示可选项;
  • 调用时可读性强:Season.SPRING 一眼就知道意思;
  • 传错类型直接编译不通过。

三、枚举的本质

        “枚举其实就是一种特殊的类。”

在底层,Java 编译器会帮你把上面的枚举编译成类似这样:

class Season extends Enum<Season> {
    public static final Season SPRING = new Season("SPRING", 0);
    public static final Season SUMMER = new Season("SUMMER", 1);
    public static final Season AUTUMN = new Season("AUTUMN", 2);
    public static final Season WINTER = new Season("WINTER", 3);

    private Season(String name, int ordinal) {
        super(name, ordinal);
    }
}

所以:

  • 每个枚举项就是一个对象;
  • 枚举的构造方法是 private 的;
  • 每个对象有两个默认属性:
    • name():枚举项名字(如 “SPRING”)
    • ordinal():枚举项序号(从 0 开始)

四、枚举的常用方法

方法说明示例
name()返回枚举项的名称Season.SPRING.name()→ "SPRING"
ordinal()返回枚举项的序号(从 0 开始)Season.WINTER.ordinal()3
values()返回所有枚举项数组for (Season s : Season.values()) {...}
valueOf
(String name)
将字符串转为枚举项Season.valueOf("SUMMER")→Season.SUMMER

五、枚举的高级用法(带属性和构造方法)

枚举不仅能列出固定项,还能像类,带属性和方法。

示例:

public class EnumTest {
    public static void main(String[] args) {
        useSeason(Season.AUTUMN);
        System.out.println(Season.SUMMER.getChineseName());
        System.out.println(Season.SUMMER.getDescription());
        System.out.println(Season.SUMMER.ordinal());
        System.out.println(Season.AUTUMN.ordinal());
    }

    public static void useSeason(Season season){
        switch (season){
            case SPRING:
                System.out.println("春季");
                break;
            case SUMMER:
                System.out.println("夏季");
                break;
            case AUTUMN:
                System.out.println("秋季");
                break;
            case WINTER:
                System.out.println("冬季");
                break;
        }
    }
}

enum Season{
    SPRING("春天","温暖"),
    SUMMER("夏天", "炎热"),
    AUTUMN("秋天", "凉爽"),
    WINTER("冬天", "寒冷");
    
    private final String chineseName;
    private final String description;
    
    private Season(String chineseName,String description){
        this.chineseName=chineseName;
        this.description=description;
    }
    public String getChineseName(){
        return chineseName;
    }
    public String getDescription(){
        return description;
    }

}

六、枚举可以定义抽象方法

可以让每个枚举项重写自己的行为:

enum Operation {
    ADD {
        public double apply(double a, double b) { return a + b; }
    },
    SUBTRACT {
        public double apply(double a, double b) { return a - b; }
    },
    MULTIPLY {
        public double apply(double a, double b) { return a * b; }
    },
    DIVIDE {
        public double apply(double a, double b) { return a / b; }
    };

    // 定义抽象方法(每个枚举项必须实现)
    public abstract double apply(double a, double b);
}

逐层解释:

(1) public abstract double apply(double a, double b);

//定义抽象方法(每个枚举项必须实现)
public abstract double apply(double a, double b);

这一行表示:
        每个枚举项都必须实现自己的“计算方式”。
这就像在接口中定义了一个抽象方法,强制所有实现类都去实现它。
而每个枚举项(ADD、SUBTRACT…)就相当于是一个“子类对象”,它各自重写了这个方法。

(2) 每个枚举项后面的大括号 {} 是什么意思?
这些大括号其实代表“匿名子类的实现体”。
也就是说,每个枚举项都是一个“Operation 的子类对象”,
并且在这个对象内部重写了 apply 方法。
可以把它想象成下面的逻辑(伪代码):

Operation ADD = new Operation() {
    public double apply(double a, double b) { return a + b; }
};
Operation SUBTRACT = new Operation() {
    public double apply(double a, double b) { return a - b; }
};
...

所以 Operation.ADD 其实是一个对象,并且它有自己版本的 apply() 方法。

(3) 调用时是怎么执行的?

System.out.println(Operation.ADD.apply(3, 5));  // 3 + 5 = 8
System.out.println(Operation.SUBTRACT.apply(3, 5));  // 3 - 5 = -2
System.out.println(Operation.MULTIPLY.apply(3, 5));  // 3 * 5 = 15
System.out.println(Operation.DIVIDE.apply(10, 5));  // 10 / 5 = 2

当你写 Operation.ADD.apply(3, 5) 时,
Java 会自动调用 ADD 这个枚举项对象内部定义的 apply() 方法,也就是执行加法逻辑。

换句话说,每个枚举项都拥有属于自己的方法实现
而调用时,系统会自动执行对应枚举项的版本。

七、枚举的特点和应用场景

枚举的特点
特点通俗解释
每个枚举项是该枚举的一个对象就像类的实例,只不过对象是固定的,不会变
通过枚举类名访问比如 Season.SPRING
所有枚举类都是 Enum 的子类所以能用 .ordinal()、.name() 等方法
枚举可以定义成员变量就像普通类一样,可以加字段、构造器、方法
枚举项必须写在第一行因为编译器需要先生成这些对象
枚举的构造器是 private防止外部创建新的枚举对象
枚举可以定义抽象方法但所有枚举项都要实现它
应用场景
场景示例
性别Gender.MALE / Gender.FEMALE
订单状态OrderStatus.NEW / PAID / SHIPPED / DONE
文件类型FileType.TXT / PDF / DOC
支付方式PayType.ALIPAY / WECHAT / CARD

例如订单状态:

enum OrderStatus {
    NEW("待支付"),
    PAID("已支付"),
    SHIPPED("已发货"),
    DONE("已完成");

    private final String desc;
    OrderStatus(String desc) { this.desc = desc; }
    public String getDesc() { return desc; }
}

使用:

OrderStatus status = OrderStatus.NEW;
System.out.println(status.getDesc()); // 待支付
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值