枚举的引出

发现问题

public class Enumdemo01 {
   public static void main(String[] args) {
       Season spring = new Season("春天","温暖");
       Season summer = new Season("夏天","炎热");
       Season autumn = new Season("秋天","凉爽");
       Season winter = new Season("冬天","寒冷");
       //一年只有四个季节,但是通过这个方法,用户可以随意增加删改
       Season other = new Season("XXX","XXX");

  }
   static class Season{
       private String name;
       public String getName() {
           return name;
      }

       public void setName(String name) {
           this.name = name;
      }
       
       private String desc;

       public String getDesc() {
           return desc;
      }

       public void setDesc(String desc) {
           this.desc = desc;
      }

       public Season(String name,String desc){
           this.name = name;
           this.desc = desc;
      }
  }
}
  • 对于季节而言,它的对象只有四个,不会有更多

  • 按照上图这个设计思路,不能体现季节只有四个的特点,因此这样设计不好

分析问题

创建Season对象有如下特点:

  • 季节的值是有限的几个值

  • 只读,不需要修改

解决方案-枚举

  • 枚举对应英文(enumeration,简写enum)

  • 枚举是一组常量的集合

  • 可以这么理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象

枚举的两种实现方式

  1. 自定义类实现枚举

  2. 使用enum关键字实现枚举

自定义类实现枚举-应用案例

  1. 不需要提供setXXX方法,因为枚举对象值通常为只读

  2. 对枚举对象/属性使用final + static共同修饰,实现底层优化

  3. 枚举对象名通常使用全部大写,常量的命名规范

  4. 枚举对象根据需要,也可以有多个属性

static class Season{
       private String name;
       private String desc;

       public String getName() {
           return name;
      }

       public String getDesc() {
           return desc;
      }
       //将构造器私有化,目的防止直接被new出来
       private Season(String name,String desc){
           this.name = name;
           this.desc = desc;
      }
       public final static Season SPRING = new Season("春天","温暖");
       public final static Season SUMMER = new Season("夏天","炎热");
       public final static Season AUTUMN = new Season("秋天","凉爽");
       public final static Season WINTER = new Season("冬天","寒冷");
  }

enum关键字实现枚举

  1. 使用关键字enum 代替class

  2. public static final Season SPRING = new Season("春天","温暖")直接使用SPRING("春天","温暖")解读

  3. 如果有多个常量(对象)使用逗号间隔即可

  4. 如果使用enum来实现枚举,要求将定义常量对象写在前面

  5. 如果我们使用的是无参构造器,创建常量对象,则可以省略括号

enum Season2{
   SPRING("春天","温暖"),
   SUMMER("夏天","炎热"),
   AUTUMN("秋天","凉爽"),
   WINTER("冬天","寒冷");


   public String getName() {
       return name;
  }

   private String name;

   public String getDesc() {
       return desc;
  }

   private String desc;

   private Season2(String name,String desc){
       this.name = name;
       this.desc = desc;
  }

Enum常用方法说明

说明:使用关键字enum时,会隐式继承Enum类,这样我们就可以使用Enum类相关的方法

enum常用方法一览表

方法名详细描述
valueOf 传递枚举类型的Class对象和枚举常量名称给静态方法valueOf,会得到与参数匹配的枚举常量
toString 得到当前枚举常量的名称。你可以通过重写这个方法来使得到的结果更易读
equals 在枚举类型中可以直接使用“==”来比较两个枚举常量是否相等。Enum提供的这个equals()方法,也是直接使用“==”实现的。它的存在是为了在Set,List和Map中使用。注意,equals()时不可变的
hashCode Enum实现了hashCode()来和equals()保持一致。它也是不可变的
getDeclaringClass 得到枚举常量所属枚举类型的Class对象。可以用它来判断两个枚举常量是否属于同一类型
name 得到当前枚举常量的名称。建议优先使用toString()
ordinal 得到当前枚举常量的次序
compareTo 枚举类型实现了Comparable接口,这样可以用它来判断两个枚举常量的大小
clone 枚举类型不能被Clone。为了防止子类实现克隆方法,Enum实现了一个仅抛出CloneNotSupportedException异常的不变Clone()
values 返回当前枚举类中所有的常量

方法实际运用

Season2 autumn = Season2.AUTUMN;
//name():输出枚举对象的名字
System.out.println(autumn.name());
//AUTUMN

//ordinal():输出对象的次序
System.out.println(autumn.ordinal());
//2

//返回当前枚举类中所有的常量
Season2[] values = Season2.values();
for (Season2 season:values){//增强for循环
   System.out.println(season);
}
//SPRING SUMMER AUTUMN WINTER

//将字符串转化为枚举对象,字符串必须为已有的常量名,否则会报错
Season2 autumn1 = Season2.valueOf("AUTUMN");
System.out.println("autumn1" + autumn1);

//compareTo:比较两个枚举常量,比较的就是编号
System.out.println(Season2.AUTUMN.compareTo(Season2.SUMMER));
//1

Enum课堂作业

  • 题目:

    1. 声明Week枚举类,其中包含星期一至星期日的定义;

    2. 使用values返回所有的枚举数组并遍历

  • 答案:

public class EnumWeek {
   public static void main(String[] args) {
       Week[] values = Week.values();
       for (Week week:values) {
           System.out.println(week.getName());
      }
  }

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


       public String getName() {
           return name;
      }

       private String name;//每一天的名称

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

Enum使用细节

  1. 使用enum关键字后,就不能继承其他类,因为enum会隐式继承Enum,而Java是单继承机制

  2. 枚举类和普通类一样,可以实现接口,如下形式

    enum 类名 implements 接口1,接口2{}

posted on 2021-08-25 16:52  prnp  阅读(230)  评论(0)    收藏  举报