Enum介绍及高级使用

简介: 枚举较为常用,有必要总结一下使用点以及高级用法

Enum 的全称为 enumeration, 是我们较为常用的类,存放在 java.lang 包中。

public enum EnumTest {
    WALK(1, "慢走"),
    QUICK(2, "疾步"),
    RUN(3, "跑步");

    private Integer code;
    private String desc;

    EnumTest(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}

可以用if/else、switch来遍历

public static EnumTest getByCode(int code) {
    for(EnumTest et : EnumTest.values()) {
        if (et.getCode().intValue() == code) {
            System.out.println(et.getCode() + "_" + et.ordinal());
            return et;
        }
    }
    return null;
}

遍历所有定义的value。
ordinal() 方法来得到定义枚举值常量的位置顺序,初始化第一个常量的顺序为0.
image

enum 的语法结构尽管和 class 的语法不一样,但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum。
enum 不能使用 extends 关键字继承其他类,因为 enum 已经继承了 java.lang.Enum(java是单一继承)。

但使用枚举,我们需要了解一些注意事项,且可以用枚举来实现怎样的功效?

  1. 枚举类型带参数,必须要对应匹配的构造方法。
  2. 可以创建一个enum类,把它看做一个普通的类。除了它不能继承其他类了。
  3. switch()参数可以使用enum了。
  4. values()方法是编译器插入到enum定义中的static方法,所以,当你将enum实例向上转型为父类Enum是,values()就不可访问了。解决办法:在Class中有一个getEnumConstants()方法,所以即便Enum接口中没有values()方法,我们仍然可以通过Class对象取得所有的enum实例。
  5. 无法从enum继承子类,如果需要扩展enum中的元素,在一个接口的内部,创建实现该接口的枚举,以此将元素进行分组。达到将枚举元素进行分组。
  6. enum允许程序员为eunm实例编写方法。所以可以为每个enum实例赋予各自不同的行为。
  7. 以职责链(Chain of Responsibility) 的方式来使用枚举,把所有任务定义为枚举值,遍历该枚举依次进行任务处理。
  8. 使用enum的状态机,然后来动态处理任务。
  9. 枚举在初始化时,实际会对每个枚举都进行构造实例化。
    
    EnumTest(Integer code, String desc) {
        System.out.println(code + "_" + desc);
        this.code = code;
        this.desc = desc;
    }

1_慢走
2_疾步
3_跑步
WALK

我们来进行编译以及反编译,看下具体是怎样的内容:

D:\App\src\main\java\com\test>javac EnumTest.java
D:\App\src\main\java\com\test>javap EnumTest.class
Compiled from "EnumTest.java"
public final class com.test.EnumTest extends java.lang.Enum<com.test.EnumTest> {
  public static final com.test.EnumTest WALK;
  public static final com.test.EnumTest QUICK;
  public static final com.test.EnumTest RUN;
  public static com.test.EnumTest[] values();
  public static com.test.EnumTest valueOf(java.lang.String);
  public static com.test.EnumTest getByCode(int);
  public java.lang.Integer getCode();
  public void setCode(java.lang.Integer);
  static {};
}

枚举类是继承了Enum,所以枚举类不能再继承其他类。定义的枚举值,在编译之后都会生成静态不可变的枚举对象。

最后来个完整的实例:

public class soundModeDemo
{
    /**
     * 将用enum枚举去除以下方法中的switch/case
     */
    public void processAlarmEvents(AlarmEvent[] events)
    {
        AlarmEvent lastEvent = events[events.length - 1];
        byte severity = lastEvent.getAlarmData().getPerceivedSeverity();
 
        switch (lastEvent.getEventType())
        {
            case AlarmEvent.NEW_ALARM:
                if (severity != PerceivedSeverity.SEVERITY_CLEARED)
                {
                    System.out.println("playAlarmSound:"+severity);
                }
                break;
            case AlarmEvent.DELETE_ALARM:
                if (severity == PerceivedSeverity.SEVERITY_CLEARED)
                {
                    return;
                }
                System.out.println("playClearSound:"+severity);
                break;
            case AlarmEvent.SEVERITY_CHANGED:
                byte oldSeverity = lastEvent.getOriginalAlarmData().getPerceivedSeverity();
                if ((oldSeverity == PerceivedSeverity.SEVERITY_CLEARED))
                {
                    System.out.println("playAlarmSound:"+severity);
                }
                else if (severity == PerceivedSeverity.SEVERITY_CLEARED)
                {
                    System.out.println("playClearSound:"+severity);
                }
                break;
        }
    }

//带有构造方法的枚举实现

public enum SoundPlay{
    NEW_ALARM(AlarmEvent.NEW_ALARM, PerceivedSeverity.SEVERITY_CLEARED, (byte)0),
    DELETE_ALARM(AlarmEvent.DELETE_ALARM, PerceivedSeverity.SEVERITY_CLEARED, (byte)0),
    SEVERITY_CHANGED(AlarmEvent.SEVERITY_CHANGED, PerceivedSeverity.SEVERITY_CLEARED, (byte)0);
   
    private final byte perceivedSeverity = PerceivedSeverity.SEVERITY_CLEARED;

    private byte eventType;
    private byte severity;
    private byte oldSeverity;

    public void setSeverity(byte severity)
    {
        this.severity = severity;
    }
    public void setOldSeverity(byte oldSeverity)
    {
        this.oldSeverity = oldSeverity;
    }
    Private SoundPlay(byte eventType, byte severity, byte oldSeverity){
        this.eventType = eventType;
        this.severity = severity;
        this.oldSeverity = oldSeverity;
    }
   
    public void printAllValues() {
        System.out.println("eventType:"+this.eventType+
                           "  severity:"+this.severity+
                           "  oldSeverity:"+this.oldSeverity);
    }  
    public void doPlay(){
        if(this.eventType == AlarmEvent.NEW_ALARM)playNewAlarm();
        if(this.eventType == AlarmEvent.DELETE_ALARM)playDeleteAlarm();
        if(this.eventType == AlarmEvent.SEVERITY_CHANGED)playSeverityChange();
    } 
    private void playSeverityChange()
    {
        if (this.oldSeverity == perceivedSeverity){
            System.out.println("playAlarmSound:" + this.oldSeverity);
        }else if (this.severity == perceivedSeverity){
            System.out.println("playClearSound:" + this.severity);
        }
    }
    private void playDeleteAlarm()
    {
        if (this.severity == perceivedSeverity){
            return;
        }else{
            System.out.println("playClearSound:" + this.severity);
        }
    }
    private void playNewAlarm()
    {
        if (this.severity != perceivedSeverity){
            System.out.println("playAlarmSound:" + this.severity);
        }
    } 
}
public static void main(String[] args)
{
    //每次调用,都需要设置severity或oldSeverity
    SoundPlay soundPlay1 = SoundPlay.NEW_ALARM;
    soundPlay1.setSeverity((byte)4);
    soundPlay1.printAllValues();
    soundPlay1.doPlay();
}

}

//最常用标准的枚举方式

public enum SoundPlay{
    NEW_ALARM{
        @Override
        public void play(AlarmEvent event)
        {
            if (event.getAlarmData().getPerceivedSeverity() !=  PerceivedSeverity.SEVERITY_CLEARED){
                System.out.println("playAlarmSound:" + event.getAlarmData().getPerceivedSeverity());
            }
        }

        @Override
        protected byte getType()
        {
            return AlarmEvent.NEW_ALARM;
        }
    },
    DELETE_ALARM{
        @Override
        public void play(AlarmEvent event)
        {
            if (event.getAlarmData().getPerceivedSeverity() == PerceivedSeverity.SEVERITY_CLEARED){
                return;
            }else{
                System.out.println("playClearSound:" + event.getAlarmData().getPerceivedSeverity());
            }
        }
        
        @Override
        protected byte getType()
        {
            return AlarmEvent.DELETE_ALARM;
        }
    },
    SEVERITY_CHANGED {
        @Override
        public void play(AlarmEvent event)
        {
            if (event.getAlarmData().getPerceivedSeverity() == PerceivedSeverity.SEVERITY_CLEARED){
                System.out.println("playAlarmSound:" + event.getOriginalAlarmData().getPerceivedSeverity());
            }else if (event.getAlarmData().getPerceivedSeverity() == PerceivedSeverity.SEVERITY_CLEARED){
                System.out.println("playClearSound:" + event.getAlarmData().getPerceivedSeverity());
            }
        }
        
        @Override
        protected byte getType()
        {
            return AlarmEvent.DELETE_ALARM;
        }
    },
    DEFAULT{
        @Override
        public void play(AlarmEvent event)
        {
           System.out.println("没有匹配的枚举值内容,调用的默认方法!");
        }
        @Override
        protected byte getType()
        {
            return -1;
        }
    };

    public abstract void play(AlarmEvent event);
    protected abstract byte getType();
    
    public static SoundPlay valueOf(byte eventType){
        for(SoundPlay soundPlay:SoundPlay.values()){
            if(eventType==soundPlay.getType()){
                return soundPlay;
            }
        }
        return DEFAULT;
    }
}
目录
相关文章
|
5月前
|
安全 算法 编译器
【C++基础语法 枚举】C/C++ 中enum枚举量的介绍:介绍enum枚举量在C/C中的作用和使用方法
【C++基础语法 枚举】C/C++ 中enum枚举量的介绍:介绍enum枚举量在C/C中的作用和使用方法
59 2
|
5月前
|
安全 API C#
C#.Net筑基-类型系统②常见类型--枚举Enum
枚举(enum)是C#中的一种值类型,用于创建一组命名的整数常量。它们基于整数类型(如int、byte等),默认为int。枚举成员可指定值,未指定则从0开始自动递增。默认值为0。枚举可以与整数类型互相转换,并可通过`[Flags]`特性表示位域,支持位操作,用于多选场景。`System.Enum`类提供了如`HasFlag`、`GetName`等方法进行枚举操作。
|
5月前
|
程序员 测试技术 C++
[C++] enum枚举类型用法
[C++] enum枚举类型用法
75 0
|
5月前
|
前端开发
前端 TS 快速入门之六:枚举 enum
前端 TS 快速入门之六:枚举 enum
62 0
|
Java
java 枚举 enum 和 Enum
java 枚举 enum 和 Enum。
106 0
java 枚举 enum 和 Enum
VB编程:Enum创建包含12个月的枚举类型
VB编程:Enum创建包含12个月的枚举类型
349 0
|
存储 编译器 Swift
Swift-进阶 08:枚举enum
Swift-进阶 08:枚举enum
609 1
Swift-进阶 08:枚举enum
|
安全 Java 编译器
深入理解 Java 枚举 Enum 类型用法
深入理解 Java 枚举 Enum 类型用法
1318 0
|
前端开发 Java 开发者
在工作中如何使用枚举(enum)
枚举是JDK 1.5中引入的新特性,由一组固定的常量组成合法值的类型,例如一年中的季节、一周的星期数。
861 2