枚举可以看作是密封类的语法糖,该密封类在编译时仅被实例化多次以定义一组常量。
将列出一个列出不同季节的简单枚举,如下所示:
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