编程知识 cdmana.com

一文快速掌握 java 枚举的用法

一、枚举

在数学和计算机科学理论中,一个数据集的枚举 是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。枚举,就是一个可列举的有限对象的集合。

JDK1.5之前,需要自定义枚举类;

JDK1.5之后,可以使用 enum 关键字定义枚举类,写法超级简单;

JDK1.6之后,switch 语句支持枚举,使代码更简洁更健壮;

若枚举类只有一个成员,则可以作为一种单例模式的实现方式,也就是说,单例模式可以看做枚举的一个特例;

1. 应用场景

可以应用到所有可以定义出有限个值的场景,常常用于设定为常量,比如:

  1. 一年有四季,定义四季的名称;
  2. 一年有12个月,定义月份的名称;
  3. 所有颜色都是有3个原色组成的,可以定义3个原色;

2. 典型应用

线程的状态是使用枚举类实现的,java.lang.Thread.State,可以看到其定义了线程的各个状态。

@Test
 public void testTheadState(){
     //获取枚举对象,并循环输出
     Thread.State[] states = Thread.State.values();
     for(Thread.State s : states){
         System.out.println(s);
     }
 }

运行结果:

 NEW
 RUNNABLE
 BLOCKED
 WAITING
 TIMED_WAITING
 TERMINATED

二、代码实现

1. 自定义枚举类

/**
  * 自定义实现的枚举类——季节
  * 枚举是可列举的有限个对象的集合,一年只有四季,都可以列举出来,故适合采用枚举形式
  * 自定义枚举类的写法和单例模式类似,或者可以说,单例模式就是枚举类只有一个对象的特例。
  *
  * 自定义枚举类有以下关键点:
  * 1. 枚举类的构造方法必须私有化,不允许外部调用,防止通过外部改变枚举对象;
  * 2. 枚举类的属性必须定义为private final,避免外部修改;
  * 3. 枚举类需要自己创建枚举对象,枚举对象必须定义为public static final,提供外部访问方式。
  *
  * @author hello
  * @date 2020/11/06
  */
 public class CustomSeasonEnum {
     /**
      * 属性定义为private final,避免被外部修改
      */
     private final String seasonName;
     private final String seasonDesc;
 
     /**
      * 构造方法私有化,可指定构造方法的参数,方便实例化时赋值
      */
     private CustomSeasonEnum(String seasonName, String seasonDesc){
         this.seasonName = seasonName;
         this.seasonDesc = seasonDesc;
     }
 
     public String getSeasonName() {
         return seasonName;
     }
 
     public String getSeasonDesc() {
         return seasonDesc;
     }
 
     /**
      * 定义枚举对象,最关键的地方
      */
     public static final CustomSeasonEnum SPRING = 
         new CustomSeasonEnum("Spring","春风拂面");
     public static final CustomSeasonEnum SUMMER = 
         new CustomSeasonEnum("Summer","生如夏花");
     public static final CustomSeasonEnum AUTUMN = 
         new CustomSeasonEnum("Autumn","秋风瑟瑟");
     public static final CustomSeasonEnum WINTER = 
         new CustomSeasonEnum("Winter","冬日暖阳");
 }

编写测试用例如下:

public class CustomSeasonEnumTest {
     @Test
     public void testCustomEnum(){
         CustomSeasonEnum season = CustomSeasonEnum.SPRING;
         System.out.println(season.getSeasonName() + " : " + season.getSeasonDesc());
     }
 }

运行结果:可以看到,调用正确

 Spring : 春风拂面

2. 使用enum关键字定义枚举类

2.1 使用enum定义的枚举类

使用enum定义的枚举类,只是一种简化了形式的自定义枚举类,其也可以包含自定义属性、方法、构造方法等,相比自定义枚举类,简化了枚举对象的声明,省略了public static final及new 对象等语句,枚举对象的定义是线程安全的,故也可以使用枚举方式定义单例模式。

与自定义枚举类相比,使用enum枚举类有以下特点:

  1. 枚举对象必须放到最前面,也就是必须在其他自定义属性或方法的签名;
  2. 忽略了public static final 及 new 对象等语句;
/**
  * 使用enum关键字定义的枚举值
  */
 public enum SeasonEnum {
     /**
      * 一年四季,依次为:春天、夏天、秋天、冬天
      * 相比自定义枚举方式:
      * 1. 必须放到最前面,也就是必须在其他自定义属性或方法的签名;
      * 2. 忽略了public static final 及 new 对象等语句;
      */
     SPRING("Spring","春风拂面"),
     SUMMER("Summer","生如夏花"),
     AUTUMN("Autumn","秋高气爽"),
     WINTER("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;
     }
 }

2.2 最简单的枚举类示例

最简单的枚举形式是只有枚举对象,没有任何属性,也不声明构造方法,也没有定义方法。

//最简单的枚举示例
 public enum ColorEnum {
     RED,GREEN,BLUE;
 }
 
 //测试用例
 @Test
 public void testColorEnum(){
     //获取红色
     ColorEnum red = ColorEnum.RED;
     System.out.println(red);
     System.out.println("------");
     //获取所有对象
     ColorEnum[] colors = ColorEnum.values();
     for (ColorEnum colorEnum : colors){
         System.out.println(colorEnum);
     }
 }

运行结果:

 RED
 ------
 RED
 GREEN
 BLUE

2.3 常用方法

2.3.1 values()

 

方法作用:获取所有的枚举对象数组,可以依次遍历,并做相应判断;

方法示例:

@Test
 public void testValues(){
     ColorEnum[] colorEnums = ColorEnum.values();
     for(ColorEnum colorEnum : colorEnums){
         System.out.println(colorEnum);
     }
 }
 //运行结果:
 RED
 GREEN
 BLUE

2.3.2 valueOf(String name)

方法作用:根据字符串获取相同名称的枚举对象;

注意事项:

  1. 要求传入的字符串名称必须是枚举对象的名称,不能随意输入;
  2. 若字符串输入错误,并不是返回null,而是程序报错;

方法示例:

(1)正确示例:获取对应名称的枚举对象

 @Test
 public void testValueOf(){
     String colorName = "RED";
     ColorEnum colorEnum = ColorEnum.valueOf(colorName);
     System.out.println(colorEnum);
 }
 //运行结果:
 RED

(2)错误示例:抛出异常IllegalArgumentException

@Test
 public void testValueOfError(){
     String colorName = "REEEEED";
     ColorEnum colorEnum = ColorEnum.valueOf(colorName);
     System.out.println(colorEnum);
 }
 //运行结果:抛出异常IllegalArgumentException
 java.lang.IllegalArgumentException: No enum constant com.tengol.demo.javase.basic.enums.ColorEnum.REEEEED
     at java.lang.Enum.valueOf(Enum.java:238)
     at com.tengol.demo.javase.basic.enums.ColorEnum.valueOf(ColorEnum.java:3)

2.4 枚举类实现接口

使用enum关键字定义的枚举类都继承自抽象类java.lang.Enum,因为Java不支持多继承,所以枚举类无法再继承其它类,但可以实现一个或者多个接口。

枚举类可以实现接口,同时枚举对象也可以重写所实现接口的抽象方法,通过反编译方式可以看到,枚举对象重写接口方法时通过匿名内部类方式实现。

第一步:定义接口

/**
  * 接口:打印信息
  */
 public interface Info {
     public void print();
 }

第二步:枚举类实现接口方法,枚举对象可以重写方法

public enum WeekEnum implements Info {
     /**
      * 一周七天
      */
     MONDAY{
         @Override
         public void print() {
             super.print();
         }
     },
     TUESDAY{
         @Override
         public void print() {
             System.out.println("Tuesday...");
         }
     },
     WEDNESDAY,
     THURSDAY,
     FRIDAY,
     SATURDAY,
     SUNDAY;
 
     public void print() {
         System.out.println("WeekEnum...");
     }
 }

测试用例:

@Test
 public void testImpl(){
     //周二重写了print()方法,执行重写的方法
     WeekEnum tue = WeekEnum.TUESDAY;
     tue.print();
     //周三未重写,执行WeekEnum的print()方法
     WeekEnum wed = WeekEnum.WEDNESDAY;
     wed.print();
 }

运行结果:

Tuesday...
WeekEnum...

部分笔记内容来自尚硅谷的培训视频,如有兴趣,请关注。

版权声明
本文为[独钓渔]所创,转载请带上原文链接,感谢
https://my.oschina.net/lenglingx/blog/4713374

Scroll to Top