宣告並使用基本列舉
列舉可以被認為是密封類的語法糖,它只在編譯時被例項化多次以定義一組常量。
列出不同季節的簡單列舉將宣告如下:
public enum Season {
WINTER,
SPRING,
SUMMER,
FALL
}
雖然列舉常量不一定需要全部大寫,但 Java 約定是常量的名稱完全是大寫的,單詞用下劃線分隔。
你可以在自己的檔案中宣告列舉:
/**
* This enum is declared in the Season.java file.
*/
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 the Day.java file and
* cannot be accessed outside because it's declared as private.
*/
private enum Season {
WINTER,
SPRING,
SUMMER,
FALL
}
}
最後,你不能在方法體或建構函式中宣告列舉:
public class Day {
/**
* Constructor
*/
public Day() {
// Illegal. Compilation error
enum Season {
WINTER,
SPRING,
SUMMER,
FALL
}
}
public void aSimpleMethod() {
// Legal. You can declare a primitive (or an Object) inside a method. Compile!
int primitiveInt = 42;
// Illegal. Compilation error.
enum Season {
WINTER,
SPRING,
SUMMER,
FALL
}
Season season = Season.SPRING;
}
}
不允許重複的列舉常量:
public enum Season {
WINTER,
WINTER, //Compile Time Error : Duplicate Constants
SPRING,
SUMMER,
FALL
}
列舉的每個常量預設為 public
,static
和 final
。由於每個常量都是 static
,因此可以使用列舉名稱直接訪問它們。
列舉常量可以作為方法引數傳遞:
public static void display(Season s) {
System.out.println(s.name()); // name() is a built-in method that gets the exact name of the enum constant
}
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 // false
Season.SPRING == Season.SPRING // true
比較列舉常量的另一種方法是使用如下的 equals()
,這被認為是不好的做法,因為你很容易陷入陷阱,如下所示:
Season.FALL.equals(Season.FALL); // true
Season.FALL.equals(Season.WINTER); // false
Season.FALL.equals("FALL"); // false 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("The count of " + name() + " is " + count);
}
}
// Usage:
MutableExample.A.print(); // Outputs 0
MutableExample.A.increment();
MutableExample.A.print(); // Outputs 1 -- we've changed a field
MutableExample.B.print(); // Outputs 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