枚举

268 阅读4分钟

枚举是什么?

维基百科的定义

数学计算机科学理论中,一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。 枚举在日常生活中很常见,例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY就是一个枚举。

枚举在C/C++/c#中,是一个被命名的整型常数的集合

enum 枚举名{
标识符[=整型常数],
标识符[=整型常数],
...
标识符[=整型常数]
}枚举变量;

如果枚举没有初始化,即省掉"=整型常数"时, 则从第一个标识符开始,顺次赋给标识符0, 1, 2, ...。但当枚举中的某个成员赋值后,其后的成员按依次加1的规则确定其值。

随着计算机的不断普及,程序不仅只用于数值计算,还更广泛地用于处理非数值的数据。例如:性别、月份、星期几、颜色、单位名、学历、职业等,都不是数值数据。 在其它程序设计语言中,一般用一个数值来代表某一状态,这种处理方法不直观,易读性差。如果能在程序中用自然语言中有相应含义的单词来代表某一状态,则程序就很容易阅读和理解。也就是说,事先考虑到某一变量可能取的值,尽量用自然语言中含义清楚的单词来表示它的每一个值,这种方法称为枚举方法,用这种方法定义的类型称枚举类型

java的枚举

java的枚举类型(enum type), 是指由一组固定常量组成合法的类型。Java中由关键字enum来定义一个枚举类型。下面就是java枚举类型的定义。

public enum Week {
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY;
}

书写注意

  • 使用关键字enum
  • 类型名称,比如这里的Week
  • 一串允许的值,比如上面定义的星期
  • 枚举可以单独定义在一个文件中,也可以嵌在其它Java类中
  • 枚举可以实现一个或多个接口(Interface)
  • 可以定义新的变量
  • 可以定义新的方法
  • 可以定义根据具体枚举值而相异的类

API

方法名称描述
values()以数组形式返回枚举类型的所有成员
valueOf()将普通字符串转换为枚举实例
compareTo()比较两个枚举成员在定义时的顺序
ordinal()获取枚举成员的索引位置

用法

  • 常量
public enum week {
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY;
} 
  • switch
public class emumTest {
    Week today = Week.SUNDAY;
    public void method() {
        Week week = null;
        switch (today) {
            case MONDAY:
                week = Week.MONDAY;
                break;
            case TUESDAY:
                week = Week.TUESDAY;
                break;
            case WEDNESDAY:
                week = Week.WEDNESDAY;
                break;
            default:
                break;
        }
       
    }
}
  • 向枚举中添加新方法

public enum Week {
    SUNDAY("星期日",1),
    SATURDAY("星期六",2);
    private String name;
    private int index;

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

    // 普通方法
    public static String getName(int index) {
        for (Week c : Week.values()) {
            if (c.getIndex() == index) {
                return c.name;
            }
        }
        return null;
    }

    //setget...
}

public class emumTest {
  public static void main(String[] args) {
        System.out.println(Week.SATURDAY);  //SATURDAY
        System.out.println(Week.SATURDAY.getName());//星期六
        System.out.println(Week.SUNDAY);//SUNDAY
        System.out.println(Week.getName(1));//星期日

    }
}
  • 覆盖枚举的方法 (重写toString)
@Override
public String toString() {
    return this.name + "-" + this.index;
}

public class emumTest {
     public static void main(String[] args) {
        System.out.println(Week.SATURDAY);  //星期六-2
        System.out.println(Week.SATURDAY.getName());//星期六
        System.out.println(Week.SUNDAY);//星期日-1
        System.out.println(Week.getName(1));//星期日
    }
}
  • 实现接口
public interface Behaviour {
    void print();
    String getInfo();
}
enum Week2 implements Behaviour{
    SUNDAY("星期日",1),
    SATURDAY("星期六",2);// 成员变量
    private String name;
    private int index;
    // 构造方法
    private Week2(String name, int index) {
        this.name = name;
        this.index = index;
    }
    //接口方法
    @Override
    public String getInfo() {
        return this.name;
    }
    //接口方法
    @Override
    public void print() {
        System.out.println(this.index+":"+this.name);
    }
}

System.out.println(Week2.SATURDAY.getInfo());//星期六
  • 使用接口组织枚举
public interface Food {
    enum Coffee implements Food{
        BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
    }
    enum Dessert implements Food{
        FRUIT, CAKE, GELATO
    }
}

System.out.println(Food.Coffee.BLACK_COFFEE);//BLACK_COFFEE

好处

  • 简化代码

    见名知意

  • 线程安全

    第一次使用到的时候,虚拟机会对其进行初始化、类加载操作,这个过程是线程安全的

  • 序列化安全

    因为Java的序列化规定,对于enum类型的对象,在序列化的时候只是保存了一个名字,当再次进行反序列化的时候,它会根据这个名字到虚拟机中去找这个enum对象,这期间的writeObject,readObject等等一系列调用全部禁用,所以说枚举是序列化安全的。

    序列化www.jianshu.com/p/35ddcf46a…

注意

枚举的常量在作为方法参数传参时, 和普通字符串不一样, 只有方法的参数声明中使用枚举类型时, 才可以传参

常量有类型, 枚举也是一种类型, 使用时类型要一致

参考资料

www.hollischuang.com/archives/19…

www.jianshu.com/p/535aff3c4…

baike.baidu.com/item/%E6%9E…