Java枚举

73 阅读4分钟

概念

Java枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。我们定义枚举类就是把具体的对象一个一个列举出来。

所谓枚举是指将变量的值一一列举出来,变量只限于列举出来的值的范围内取值。

实际开发中,常常定义一些不常更改的常量。

枚举的来源

一个现象是:一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,比如:方向,性别,星期,季节。这也是一个问题!

在Java5之前,是采用自定义带有枚举功能的类解决的,我们定义有些复杂常量会这么写:就是自定义一个类,然后是私有化构造函数,在自定义类中创建本类的对象对外使用。如下例子

class Gender{
  String value;
  public static final Gender man = new Gender("男");
  public static final Gender woman = new Gender("女");
  
  private Gender(String value) {
    super();
    this.value = value;
  }
}

在Java5对以上问题提出了新的解决方案:就是使用枚举类解决。

enum Gender{
  man("男"),
  woman("女"),
  ;
  String value;
  private Gender(String value) {
    this.value = value;
  }
}

示例

Java枚举类使用enum关键字来定义,各个常量(实例)使用逗号 , 来分割。

public enum Color 
{ 
    RED, GREEN, BLUE,; 
} 

枚举类(Enum)的细节

1.枚举类也是一个特殊的类。

2.枚举值默认的修饰符是public static final

3.枚举值是枚举值所属的类的类型,然后枚举值是指向了本类的对象的。

4.枚举类的构造方法默认的修饰符是private。

5.枚举类可以定义自己的成员变量与成员函数。

6.枚举类可以自定义构造函数,但是构造函数的修饰符必须是private。

7.枚举类可以存在抽象的方法,但是枚举值必须要实现抽象的方法。

8.枚举值必须要位于枚举类的第一个语句。

9.enum定义的枚举类默认继承了java.lang.Enum类,并实现了java.lang.Serializable和java.lang.Comparable两个接口。由于Java不支持多继承,所以枚举类对象不能再继承其他类。

相关方法

values()

values()返回含有定义的所有枚举对象数组。

ordinal()

ordinal()输出的是该枚举对象的次序/编号/索引/下标,从0开始编号。

valueOf()

根据定义的name去找定义的枚举实例,如果找到了,就返回这个对象的具体信息,如果没有找到,就报错。

name()

返回实例名。

getDeclaringClass()

返回实例所属的enum类型

compareTo()

枚举比较大小,返回结果实际上是该对象ordinal值减去入参ordinal值,两枚举实例如果相同则返回0。

常用场景

(一)常量

(二)switch

(三)向枚举中添加新字段、新方法、覆盖Enum的方法

(四)实现接口和使用接口组织枚举(Java多态)

枚举的扩展

EnumSet

java.util.EnumSet是枚举类型的高性能Set实现,它要求放入它的枚举常量必须属于同一枚举类类型。

与TreeSet/HashSet不同,EnumSet是一个抽象类,不能直接通过new新建。不过,EnumSet提供了若干静态工厂方法,可以创建EnumSet类型的对象。

相关方法

// noneOf方法会创建一个指定枚举类型的EnumSet,不含任何元素。创建的EnumSet对象的实际类型是EnumSet的子类
<E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType)
// 初始集合包括指定枚举类型的所有枚举值
<E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType)
// 初始集合包括枚举值中指定范围的元素
<E extends Enum<E>> EnumSet<E> range(E from, E to)
// 初始集合包括指定集合的补集
<E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s)
// 初始集合包括参数中的所有元素
<E extends Enum<E>> EnumSet<E> of(E e)
<E extends Enum<E>> EnumSet<E> of(E e1, E e2)
<E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3)
<E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4)
<E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5)
<E extends Enum<E>> EnumSet<E> of(E first, E... rest)
// 初始集合包括参数容器中的所有元素
<E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s)
<E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c)

我们以noneOf()为例

enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

Set<Day> weekend = EnumSet.noneOf(Day.class);
weekend.add(Day.SATURDAY);
weekend.add(Day.SUNDAY);
System.out.println(weekend);//weekend表示休息日,noneOf返回的Set为空,添加了周六和周日,所以输出为[SATURDAY, SUNDAY]

EnumMap

Map接口的实现,其key-value映射中的key是Enum类型。

java.util.EnumMap是专门为枚举类型定制的Map,EnumMap在使用上跟HashMap差不多,但是EnumMap的性能更好,所以,如果键为Enum类型时,建议使用EnumMap代替HashMap。

package com.pichen.collection;
 
import java.util.EnumMap;
import java.util.Map;
import java.util.Map.Entry;
 
enum Operate{
    ADD, UPDATE, DELETE; 
}
 
public class Main {
    public static void main(String[] args) {
        Map<Operate, String> map = new EnumMap<Operate, String>(Operate.class);
        //put方法
        map.put(Operate.ADD, "add operate");
        map.put(Operate.UPDATE, "update operate");
        map.put(Operate.DELETE, "delete operate");
 
        //重写了toString方法
        System.out.println(map);
 
        //size方法
        System.out.println(map.size());
 
        System.out.println(map.containsKey(Operate.UPDATE));
        System.out.println(map.containsValue("update operate"));
        System.out.println(map.get(Operate.DELETE));
 
        //remove
        map.remove(Operate.UPDATE);
        System.out.println(map);
 
        //key集合
        for(Operate operate:map.keySet()){
            System.out.print(operate + " ");
        }
 
        System.out.println();
        //value集合
        for(String obj:map.values()){
            System.out.print(obj + ",");
        }
 
        System.out.println();
        //key-value集合
        for(Entry<Operate, String> entry:map.entrySet()){
            System.out.print(entry.getKey() + ": " + entry.getValue() + ", ");
        }
    }
}


开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情