枚举类型
枚举类型的基本特性
- 创建枚举类型时,编译器会自动生成一个辅助类,这个类自动继承自
java.lang.Enum
,包含的功能有:ordinal()
:返回一个从0开始的int值,代表每个枚举实例的声明顺序- 可以直接使用
==
来比较枚举实例(equals()
与hashCode()
方法编译器自动生成) - 实现了
Comparable
接口,可以直接进行比较- 自动包含了
compareTo()
方法
- 自动包含了
- 实现了
Serializable
接口 getDeclareingClass()
可以得到该枚举实例所属的外部包装类name()
方法返回枚举实例被声明的名称- 使用
toString()
方法可以达到同样的目的
- 使用
valueOf()
是Enum
类中的静态方法,它根据传入的String
,返回名称与该String
匹配的枚举类型- 如果匹配的实例不存在,则抛出异常
- 通过
static import
将所有的枚举类型标识符都引入本地的命名空间- 这样的方式可以不需要显式的使用枚举类型来限定,可以直接在代码中使用
package enums; import static enums.SpicinessEnum.*; public class Burrito2 { SpicinessEnum degree; public Burrito2(SpicinessEnum degree) { this.degree = degree; } @Override public String toString() { return "Burrito is "+ degree; } public static void main(String[] args) { System.out.println(new Burrito2(NOT)); System.out.println(new Burrito2(MEDIUM)); System.out.println(new Burrito2(HOT)); } } /* Output: Burrito is NOT Burrito is MEDIUM Burrito is HOT */
- 这样的方式可以不需要显式的使用枚举类型来限定,可以直接在代码中使用
在枚举类型中增加自定义的方法
对于枚举类型来说,除了无法继承(final)它以外,可以将其看做一个普通的类。 这意味着你可以在里面增加自定义的方法,甚至是一个
main()
方法 但是实例必须在方法之前定义 - 如果想要增加自定义方法,则必须在方法之前定义枚举实例的序列 - 构造方法: - 构造方法的类型必须是包级或者是private
:在枚举定义完成之后,编译器不会允许使用它来创建任何新的类型 - 重载枚举类型中的方法与重载任何普通类的方法一致
在switch
语句中使用枚举
由于enum内部已经构建了一个整型序列,枚举类型可以非常方便的用在switch语句中,并且可以通过ordinal()方法来得到枚举实例的顺序
编译器不会因为该Signal color = Signal.RED; public void change() { switch(color) { // Note you don't have to say Signal.RED // in the case statement: case RED: color = Signal.GREEN; break; case GREEN: color = Signal.YELLOW; break; case YELLOW: color = Signal.RED; break; } }
switch
中没有default
而报错,因此在使用switch
时必须小心,确保手动覆盖了所有分支。 但是,如果在case
语句中调用了return
,而没有编写default
,编译器会报错
values()方法
values()
方法是由编译器添加的一个静态方法- 由于
values()
方法是由编译器在枚举类的定义中插入的一个静态方法,因此如果将其向上转型为Enum,则无法使用该方法- 可以通过其
Class
对象的getEnumConstant()
来得到enum
的实例
- 可以通过其
实现,而不是继承
由于所有的enum类都默认继承java.lang.Enum,而java不支持多继承,因此无法自行通过继承方式创建一个枚举对象 不过可以通过实现接口的方式
// enums/cartoons/EnumImplementation.java // (c)2021 MindView LLC: see Copyright.txt // We make no guarantees that this code is fit for any purpose. // Visit http://OnJava8.com for more book information. // An enum can implement an interface // {java enums.cartoons.EnumImplementation} package enums.cartoons; import java.util.*; import java.util.function.*; enum CartoonCharacter implements Supplier<CartoonCharacter> { SLAPPY, SPANKY, PUNCHY, SILLY, BOUNCY, NUTTY, BOB; private Random rand = new Random(47); @Override public CartoonCharacter get() { return values()[rand.nextInt(values().length)]; } } public class EnumImplementation { public static <T> void printNext(Supplier<T> rg) { System.out.print(rg.get() + ", "); } public static void main(String[] args) { // Choose any instance: CartoonCharacter cc = CartoonCharacter.BOB; for(int i = 0; i < 10; i++) printNext(cc); } } /* Output: BOB, PUNCHY, BOB, SPANKY, NUTTY, PUNCHY, SLAPPY, NUTTY, NUTTY, SLAPPY, */
随机选择
使用接口来组织枚举
可以在一个接口内对原宿进行分组,然后基于这个接口生成一个枚举,通过这样的方式来实现元素的分类
// enums/menu/Food.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Subcategorization of enums within interfaces
package enums.menu;
public interface Food {
enum Appetizer implements Food {
SALAD, SOUP, SPRING_ROLLS;
}
enum MainCourse implements Food {
LASAGNE, BURRITO, PAD_THAI,
LENTILS, HUMMUS, VINDALOO;
}
enum Dessert implements Food {
TIRAMISU, GELATO, BLACK_FOREST_CAKE,
FRUIT, CREME_CARAMEL;
}
enum Coffee implements Food {
BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
LATTE, CAPPUCCINO, TEA, HERB_TEA;
}
}