9.1 概述

  • 枚举类型本质上也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。
  • 枚举类的例子举不胜举:
  • 星期:Monday(星期一)......Sunday(星期天)
  • 性别:Man(男)、Woman(女)
  • 月份:January(1月)......December(12月)
  • 季节:Spring(春节)......Winter(冬天)
  • 三原色:red(红色)、green(绿色)、blue(蓝色)
  • 支付方式:Cash(现金)、WeChatPay(微信)、Alipay(支付宝)、BankCard(银行卡)、CreditCard(信用卡)
  • 就职状态:Busy(忙碌)、Free(空闲)、Vocation(休假)、Dimission(离职)
  • 订单状态:Nonpayment(未付款)、Paid(已付款)、Fulfilled(已配货)、Delivered(已发货)、Checked(已确认收货)、Return(退货)、Exchange(换货)、Cancel(取消)
  • 线程状态:创建、就绪、运行、阻塞、死亡
  • 若枚举只有一个对象, 则可以作为一种单例模式的实现方式。
  • 枚举类的实现:
  • 在JDK5.0 之前,需要程序员自定义枚举类型。
  • 在JDK5.0 之后,Java支持enum关键字来快速定义枚举类型。

9.2 定义枚举类(JDK5.0 之前)

在JDK5.0 之前如何声明枚举类呢?

  • 私有化类的构造器,保证不能在类的外部创建其对象
  • 在类的内部创建枚举类的实例。声明为:public static final ,对外暴露这些常量对象
  • 对象如果有实例变量,应该声明为private final(建议,不是必须),并在构造器中初始化

示例代码:

class Season{
    private final String SEASONNAME;//季节的名称
    private final String SEASONDESC;//季节的描述
    private Season(String seasonName,String seasonDesc){
        this.SEASONNAME = seasonName;
        this.SEASONDESC = seasonDesc;
    }
    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("冬天", "白雪皑皑");

    @Override
    public String toString() {
        return "Season{" +
                "SEASONNAME='" + SEASONNAME + '\'' +
                ", SEASONDESC='" + SEASONDESC + '\'' +
                '}';
    }
}
class SeasonTest{
    public static void main(String[] args) {
        System.out.println(Season.AUTUMN);
    }
}


9.3 定义枚举类(JDK5.0 之后)

9.3.1 enum关键字声明枚举


【修饰符】 enum 枚举类名{    常量对象列表 } 【修饰符】 enum 枚举类名{    常量对象列表;        对象的实例变量列表; }


举例1:


package com.atguigu.enumeration;

public enum Week {
    MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
}
 
public class TestEnum {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        System.out.println(spring);
    }
}


9.3.2 enum方式定义的要求和特点
  • 枚举类的常量对象列表必须在枚举类的首行,因为是常量,所以建议大写。
  • 列出的实例系统会自动添加 public static final 修饰。
  • 如果常量对象列表后面没有其他代码,那么“;”可以省略,否则不可以省略“;”。
  • 编译器给枚举类默认提供的是private的无参构造,如果枚举类需要的是无参构造,就不需要声明,写常量对象列表时也不用加参数
  • 如果枚举类需要的是有参构造,需要手动定义,有参构造的private可以省略,调用有参构造的方法就是在常量对象名后面加(实参列表)就可以。
  • 枚举类默认继承的是java.lang.Enum类,因此不能再继承其他的类型。
  • JDK5.0 之后switch,提供支持枚举类型,case后面可以写枚举常量名,无需添加枚举类作为限定。

举例2:


public enum SeasonEnum {
    SPRING("春天","春风又绿江南岸"),
    SUMMER("夏天","映日荷花别样红"),
    AUTUMN("秋天","秋水共长天一色"),
    WINTER("冬天","窗含西岭千秋雪");

    private final String seasonName;
    private final String seasonDesc;
    
    private SeasonEnum(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }
    public String getSeasonName() {
        return seasonName;
    }
    public String getSeasonDesc() {
        return seasonDesc;
    }
}


举例3:


package com.atguigu.enumeration;

public enum Week {
    MONDAY("星期一"),
    TUESDAY("星期二"),
    WEDNESDAY("星期三"),
    THURSDAY("星期四"),
    FRIDAY("星期五"),
    SATURDAY("星期六"),
    SUNDAY("星期日");

    private final String description;

    private Week(String description){
        this.description = description;
    }

    @Override
    public String toString() {
        return super.toString() +":"+ description;
    }
}
 
package com.atguigu.enumeration;

public class TestWeek {
    public static void main(String[] args) {
        Week week = Week.MONDAY;
        System.out.println(week);

        switch (week){
            case MONDAY:
                System.out.println("怀念周末,困意很浓");break;
            case TUESDAY:
                System.out.println("进入学习状态");break;
            case WEDNESDAY:
                System.out.println("死撑");break;
            case THURSDAY:
                System.out.println("小放松");break;
            case FRIDAY:
                System.out.println("又信心满满");break;
            case SATURDAY:
                System.out.println("开始盼周末,无心学习");break;
            case SUNDAY:
                System.out.println("一觉到下午");break;
        }
    }
}


经验之谈:

开发中,当需要定义一组常量时,强烈建议使用枚举类。

9.4 enum中常用方法


String toString(): 默认返回的是常量名(对象名),可以继续手动重写该方法!     static 枚举类型[] values():返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值,是一个静态方法     static 枚举类型 valueOf(String name):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运行时异常:IllegalArgumentException。     String name():得到当前枚举常量的名称。建议优先使用toString()。     int ordinal():返回当前枚举常量的次序号,默认从0开始


举例:


package com.atguigu.enumeration;

import java.util.Scanner;

public class TestEnumMethod {
    public static void main(String[] args) {
        //values()
        Week[] values = Week.values();
        for (int i = 0; i < values.length; i++) {
            //ordinal()、name()
            System.out.println((values[i].ordinal()+1) + "->" + values[i].name());
        }
        System.out.println("------------------------");

        Scanner input = new Scanner(System.in);
        System.out.print("请输入星期值:");
        int weekValue = input.nextInt();
        Week week = values[weekValue-1];
        //toString()
        System.out.println(week);

        System.out.print("请输入星期名:");
        String weekName = input.next();
        //valueOf()
        week = Week.valueOf(weekName);
        System.out.println(week);

        input.close();
    }
}


9.5 实现接口的枚举类

  • 和普通 Java 类一样,枚举类可以实现一个或多个接口
  • 若每个枚举值在调用实现的接口方法呈现相同的行为方式,则只要统一实现该方法即可。
  • 若需要每个枚举值在调用实现的接口方法呈现出不同的行为方式,则可以让每个枚举值分别来实现该方法

语法:


//1、枚举类可以像普通的类一样,实现接口,并且可以多个,但要求必须实现里面所有的抽象方法!
enum A implements 接口1,接口2{
    //抽象方法的实现
}

//2、如果枚举类的常量可以继续重写抽象方法!
enum A implements 接口1,接口2{
    常量名1(参数){
        //抽象方法的实现或重写
    },
    常量名2(参数){
        //抽象方法的实现或重写
    },
    //...
}


举例:


interface Info{
    void show();
}

//使用enum关键字定义枚举类
enum Season1 implements Info{
    //1. 创建枚举类中的对象,声明在enum枚举类的首位
    SPRING("春天","春暖花开"){
        public void show(){
            System.out.println("春天在哪里?");
        }
    },
    SUMMER("夏天","夏日炎炎"){
        public void show(){
            System.out.println("宁静的夏天");
        }
    },
    AUTUMN("秋天","秋高气爽"){
        public void show(){
            System.out.println("秋天是用来分手的季节");
        }
    },
    WINTER("冬天","白雪皑皑"){
        public void show(){
            System.out.println("2002年的第一场雪");
        }
    };
    
    //2. 声明每个对象拥有的属性:private final修饰
    private final String SEASON_NAME;
    private final String SEASON_DESC;
    
    //3. 私有化类的构造器
    private Season1(String seasonName,String seasonDesc){
        this.SEASON_NAME = seasonName;
        this.SEASON_DESC = seasonDesc;
    }
    
    public String getSEASON_NAME() {
        return SEASON_NAME;
    }

    public String getSEASON_DESC() {
        return SEASON_DESC;
    }
}


个人思考总结:

Java枚举类(Enum)是一种特殊的数据类型,用于表示一组常量值。枚举类可以帮助程序员更清晰地表示有限的、预定义的选项,提高代码的可读性和可维护性。

  1. 枚举类的定义:枚举类通过关键字 enum 来定义。它们在Java中是一种特殊的类,可以包含字段和方法。
  2. 预定义常量:枚举类允许在一个地方列出所有相关的常量。这些常量在枚举类中是唯一的,并且可以通过枚举类型的名称来访问。
    enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
  3. 类型安全性:枚举类提供了类型安全性,因为它们只能包含定义的常量。这可以避免使用不正确的值。
  4. 可读性:枚举类的常量通常使用大写字母,这有助于提高代码的可读性,因为它们在代码中很容易识别。
  5. 枚举方法:可以向枚举类添加方法,这些方法可以与枚举常量一起工作。例如,可以在枚举类中添加一个方法来获取常量的描述。
    enum Color { RED("红色"), GREEN("绿色"), BLUE("蓝色"); private String description; Color(String description) { this.description = description; } public String getDescription() { return description; } }
  6. 枚举的迭代:可以使用values()方法遍历枚举的所有常量,这对于循环处理枚举常量非常有用。
    for (Day day : Day.values()) { System.out.println(day); }
  7. switch语句的优势:枚举类常常用于替代复杂的if-else或switch语句,使代码更加清晰和易于维护。
    switch (day) { case MONDAY: // Do something for Monday break; case TUESDAY: // Do something for Tuesday break; // ... }
  8. 枚举的内部实现:Java枚举类的内部实现通常是通过类似单例模式的方式实现的,确保每个常量只有一个实例。