初探Java枚举类

目录

  • 1.何为枚举
  • 2.枚举本质
  • 3.枚举特性
    • 3.1基本特性
    • 3.2枚举方法
    • 3.3 枚举接口
    • 3.4 获取枚举元素
    • 3.5 状态机
  • 4.枚举工具类
    • 4.1EnumSet
    • 4.2EnumMap
  • 5.总结

1.何为枚举

枚举是一种数据类型,具有集合的一些特点,可以存放多个元素,但存储对象有限且固定,枚举也有比较常见的使用场景。如性别(男、女),颜色(红、黄、蓝),星期(星期一、星期二…星期日)均可以使用枚举存储。

2.枚举本质

从源码角度:


public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
        }

实质上Enum是java.lang.Enum 的子类。

  • 示例:
//定义颜色枚举
public enum ColorEnum {
    RED,YELLOW,BLUE
}

分别编译文件和反编译

> javac ColorEnum.java
> javap ColorEnum.class
Compiled from "ColorEnum.java"
public final class com.qxy.config.ColorEnum extends java.lang.Enum<com.qxy.config.ColorEnum> {
  public static final com.qxy.config.ColorEnum RED;
  public static final com.qxy.config.ColorEnum YELLOW;
  public static final com.qxy.config.ColorEnum BLUE;
  public static com.qxy.config.ColorEnum[] values();
  public static com.qxy.config.ColorEnum valueOf(java.lang.String);
  static {};
}

从反编译文件中可以得出以下结论:

  • 定义的枚举值作为枚举类的属性,会被默认修饰为 public static final ,从修饰关键字,即可看出枚举值本质上是静态常量。
  • 枚举类属于final类型,无法继承。
  • 针对枚举属性,可以将其理解为实例对象,且具备属性方法。

3.枚举特性

枚举的特性,归结起来就是一句话:
除了不能继承,基本上可以将 enum 看做一个常规的类。

3.1基本特性

  • 如果枚举中没有定义方法,也可以在最后一个实例后面加逗号、分号或什么都不加。
    如:
public enum ColorEnum {
    RED,YELLOW,BLUE
}
  • 如果枚举中没有定义方法,枚举值默认为从 0 开始的有序数值。以 Color 枚举类型举例,它的枚举常量依次为 RED:0,GREEN:1,BLUE:2。
//ordinal():返回实例声明时的次序,从 0 开始。
    public static void main(String[] args) {
        System.out.println(ColorEnum.RED.ordinal());//0
    }

3.2枚举方法

  • Java 不允许使用 = 为枚举常量赋值;
  • 创建 enum 时,可以为其添加多种方法,甚至可以为其添加构造方法。
注意一个细节:如果要为 enum 定义方法,那么必须在 enum 的最后一个实例尾部添加一个分号[;]。
此外,在 enum 中,必须先定义实例,不能将字段或方法定义在实例前面。否则,编译器会报错。

示例:

public enum ColorEnum {
    RED("red"),YELLOW("yellow"),BLUE("blue");
    private String code;

    // 有参构造方法
    ColorEnum(String code) {
        this.code = code;
    }

    //普通方法
    public String getCode() {
        return code;
    }

    //静态方法
    public static void main(String[] args) {
        System.out.println(ColorEnum.RED.ordinal());
    }
}

3.3 枚举接口

enum 不可以继承另外一个类,当然,也不能继承另一个 enum ?因为 enum 实际上都继承自 java.lang.Enum 类,而 Java 不支持多重继承,所以 enum 不能再继承其他类,当然也不能继承另一个 enum。但是枚举可以定义接口并实现。
示例:

public interface IEnum<E extends Serializable> {
    E getValue();
}
//实现Enum接口
public enum ColorEnum implements IEnum<String>{
    RED("red"),YELLOW("yellow"),BLUE("blue");
    private String code;

    // 有参构造方法
    ColorEnum(String code) {
        this.code = code;
    }

    //静态方法
    public static void main(String[] args) {
        ColorEnum red = ColorEnum.RED;
        System.out.println(red.ordinal() + ":" + red.getValue());//0:red
    }

    //重写接口方法,并返回值
    @Override
    public String getValue() {
        return code;
    }
}

3.4 获取枚举元素

public static void main(String[] args) {
        //获取枚举元素
        System.out.println(ColorEnum.RED);
        System.out.println(ColorEnum.RED.toString());
        System.out.println("-------------");
        //获取枚举属性
        System.out.println(ColorEnum.RED.code);
        System.out.println(ColorEnum.RED.getValue());
    }
//
RED
RED
-------------
red
red

3.5 状态机

使用 switch 语句来写状态机。JDK7 以后,switch 已经支持 int、char、String、enum 类型的参数。这几种类型的参数比较起来,使用枚举的 switch 代码更具有可读性。

public class StateMachineDemo {
    public enum Signal {
        GREEN, YELLOW, RED
    }

    public static String getTrafficInstruct(Signal signal) {
        String instruct = "信号灯故障";
        switch (signal) {
            case RED:
                instruct = "红灯停";
                break;
            case YELLOW:
                instruct = "黄灯请注意";
                break;
            case GREEN:
                instruct = "绿灯行";
                break;
            default:
                break;
        }
        return instruct;
    }

    public static void main(String[] args) {
        System.out.println(getTrafficInstruct(Signal.RED));
    }
}

4.枚举工具类

Java 中提供了两个方便操作 enum 的工具类——EnumSet 和 EnumMap。

4.1EnumSet

EnumSet 是枚举类型的高性能 Set 实现。它要求放入它的枚举常量必须属于同一枚举类型。
主要接口:

  • noneOf - 创建一个具有指定元素类型的空 EnumSet。
  • allOf - 创建一个指定元素类型并包含所有枚举值的 EnumSet。
  • range - 创建一个包括枚举值中指定范围元素的 EnumSet。
  • complementOf - 初始集合包括指定集合的补集。
  • of - 创建一个包括参数中所有元素的 EnumSet。
  • copyOf - 创建一个包含参数容器中的所有元素的 EnumSet。
public static void main(String[] args) {
        EnumSet<ColorEnum> enums = EnumSet.allOf(ColorEnum.class);
        for (ColorEnum colorEnum : enums) {
            System.out.println(colorEnum.getValue());
        }

    }

4.2EnumMap

EnumMap 是专门为枚举类型量身定做的 Map 实现。虽然使用其它的 Map 实现(如 HashMap)也能完成枚举类型实例到值得映射,但是使用 EnumMap 会更加高效:它只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以 EnumMap 使用数组来存放与枚举类型对应的值。这使得 EnumMap 的效率非常高。
主要接口:

  • size - 返回键值对数
  • containsValue - 是否存在指定的 value
  • containsKey - 是否存在指定的 key
  • get - 根据指定 key 获取 value
  • put - 取出指定的键值对
  • remove - 删除指定 key
  • putAll - 批量取出键值对
  • clear - 清除数据
  • keySet - 获取 key 集合
  • values - 返回所有

5.总结

枚举完美地解决了之前通过常量来表示离散量所带来的问题,大大加强了程序的可读性、易用性和可维护性,并且在此基础之上又进行了扩展,使之可以像类一样去使用,更是为Java对离散量的表示上升了一个台阶。因此,如果在Java中需要表示诸如颜色、方式、类别、状态等等数目有限、形式离散、表达又极为明确的量,应当尽量舍弃常量表示的做法,而将枚举作为首要的选择。

你可能感兴趣的:(java,java,enum)