Java声明和使用基本枚举

示例

枚举可以看作是密封类的语法糖,该密封类在编译时仅被实例化多次以定义一组常量。

将列出一个列出不同季节的简单枚举,如下所示:

public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

尽管枚举常量不必一定要全部大写,但Java惯例是,常量名称完全是大写的,单词之间用下划线分隔。


您可以在自己的文件中声明一个Enum:

/**
 * This enum is declared in theSeason.javafile.
*/
public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

但是您也可以在另一个类中声明它:

 public class Day {

    private Season season;

    public String getSeason() {
        return season.name();
    }

    public void setSeason(String season) {
       this.season= Season.valueOf(season);
    }

    /**
     * This enum is declared inside theDay.javafile and 
     * cannot be accessed outside because it's declared as private.
     */
    private enum Season {
        WINTER,
        SPRING,
        SUMMER,
        FALL
    }

}

最后,您不能在方法主体或构造函数内声明一个Enum:

public class Day {

    /**
     * Constructor
    */
    public Day() {
        //非法。编译错误
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }
    }

    public void aSimpleMethod() {
        //法律。您可以在方法内部声明原语(或对象)。编译!
        int primitiveInt = 42;

        //非法。编译错误.
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }

        Season season = Season.SPRING;
    }
    
}


不允许重复的枚举常量:

public enum Season {
    WINTER,
    WINTER, //编译时错误:常量重复
    SPRING,
    SUMMER,
    FALL
}


枚举的每一个常数public,static并且final在默认情况下。由于每个常量都是static,可以使用枚举名称直接访问它们。

枚举常量可以作为方法参数传递:

public static void display(Season s) {
    System.out.println(s.name());  // name()是一个内置方法,可获取枚举常量的确切名称
}

display(Season.WINTER);  // Prints out "WINTER"

您可以使用values()方法获得枚举常量数组。保证值在返回数组中按声明顺序排列:

Season[] seasons = Season.values();

注意:每次调用此方法时,都会分配一个新的值数组。


要遍历枚举常量:

public static void enumIterate() {
    for (Season s : Season.values()) {
        System.out.println(s.name());
    }
}

您可以在switch语句中使用枚举:

public static void enumSwitchExample(Season s) {
    switch(s) {
        case WINTER:
            System.out.println("It's pretty cold");
            break;
        case SPRING:
            System.out.println("It's warming up");
            break;
        case SUMMER:
            System.out.println("It's pretty hot");
            break;
        case FALL:
            System.out.println("It's cooling down");
            break;
    }
}

您还可以使用来比较枚举常量==:

Season.FALL ==Season.WINTER   // 假
Season.SPRING ==Season.SPRING // 真正


比较枚举常量的另一种方法是使用equals()以下方法,这被认为是不好的做法,因为您很容易陷入如下陷阱:

Season.FALL.equals(Season.FALL); // 真正
Season.FALL.equals(Season.WINTER); // 假
Season.FALL.equals("FALL"); // 假 and no compiler error

此外,尽管enum无法在运行时更改实例中的实例集,但实例本身并不是固有不变的,因为像其他任何类一样,实例enum可以包含可变字段,如下所示。

public enum MutableExample {
    A,
    B;

    private int count = 0;

    public void increment() {
        count++;
    }

    public void print() {
        System.out.println("的计数 " + name() + " is " + count);
    }
}

// 用法:
MutableExample.A.print();       // 输出0
MutableExample.A.increment();
MutableExample.A.print();       // 输出1-我们更改了一个字段   
MutableExample.B.print();       // 输出0 -- another instance remains unchanged

但是,一种好的做法是使enum实例不可变,即当它们没有任何其他字段或所有此类字段都标记为final且本身是不可变的时。这将确保在应用程序的生命周期内enum不会泄漏任何内存,并且可以安全地在所有线程中使用其实例。


枚举隐式实现,Serializable并且Comparable因为Enum该类执行以下操作:

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