Java枚举类型

简介: 关键字enum可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用。这些具名的值称为枚举值,这种新的类型称为枚举类型。      下面是一个简单的表示星期几的枚举: 1 public enum Day { 2 SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY 3 }      在创建enum时,编译器会自动添加一些有用的特性。

     关键字enum可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用。这些具名的值称为枚举值,这种新的类型称为枚举类型。

     下面是一个简单的表示星期几的枚举:

1 public enum Day {
2     SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
3 }

     在创建enum时,编译器会自动添加一些有用的特性。比如创建toString()方法以便显示某个enum实例的名字;创建ordinal()方法表示某个特定enum常量的申明顺序;values()方法用来按照enum常量的申明顺序产生这些常量构成的数组。enum看起来像是一种新的数据类型,除了编译上面这些特殊的编译行为,很大程度上可以将enum看成是一个普通的类来处理。这些内容在后面会有详细的介绍。

public static void main(String[] args) {
    System.out.println(Day.class.getSuperclass());
    for (Day day : Day.values()) {
        System.out.println(day.name() + " ordinal: " + day.ordinal());
    }
}

class java.lang.Enum

SUNDAY ordinal: 0

MONDAY ordinal: 1

TUESDAY ordinal: 2

WEDNESDAY ordinal: 3

THURSDAY ordinal: 4

FRIDAY ordinal: 5

SATURDAY ordinal: 6

     上面的代码中输出了枚举类型Day的父类及演示了values()、name()、ordinal()三个方法的调用。从输出结果中可以看到Day的父类是java.lang.Enum,但是在定义Day的时候并没有通过extends指明继承java.lang.Enum,也不需要通过extends关键字指定。当创建enum时编译器会生成一个相关的类,这个类会继承java.lang.Enum。既然枚举实例已经集成了java.lang.Enum,Java又不支持多继承,所以enum不能再继承其他的类,但是能实现接口。ordinal()方法返回一个int值,这是每个enum实例在申明时的次序,从0开始。

     除了不能继承自一个enum外,基本上可以将enum看做一个常规的类。也就是说可以向enum中添加方法,比如返回enum自身描述的方法,还可以添加main方法。下面是一个演示enum添加自定义方法和实现接口的例子。

 1 public enum Signal implements ObjectDescription {
 2     Red("红灯", "敢过去就是6分,还要罚款哦"), 
 3     Yellow("黄灯", "黄灯你也不敢过"), 
 4     Green("绿灯", "绿灯也得小心过啊");
 5 
 6     private String name;
 7     private String description;
 8 
 9     private Signal(String name, String description) {
10         this.name = name;
11         this.description = description;
12     }
13 
14     private String getName() {
15         return name;
16     }
17 
18     private String getDescription() {
19         return description;
20     }
21 
22     @Override
23     public String todo() {
24         return "Signal类用于表示交通信号指示灯," + this + "用于表示" + this.getName();
25     }
26 
27     public static void main(String[] args) {
28         for (Signal signal : Signal.values()) {
29             System.out.println(signal.todo());
30         }
31         for (Signal signal : Signal.values()) {
32             System.out.println(signal.getName() + ": "
33                     + signal.getDescription());
34         }
35     }
36 
37 }

     注意:如果要自定义方法,那么必须在enum实例序列的最后添加一个分号。同时,Java要求必须先定义enum实例,否则编译时会报错。

     enum的构造器无论是不是private,都只能在enum定义的内部使用来创建enum实例,一旦enum的定义结束,编译器就不允许再使用其构造器来创建任何实例了。

 

使用接口组织枚举

     无法使用继承限制了枚举的使用,比如需要用enum表示食物,但同时必须分为水果,点心等类型的时候就没那么方便的满足了。

     下面通过在一个接口内部创建实现该接口的枚举,从而达到对元素进行分类组织的目的。

 1 public interface Food {
 2     enum Appetizer implements Food {
 3         SALAD, SOUP, SPRING_ROLLS;
 4     }
 5 
 6     enum MainCourse implements Food {
 7         LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO;
 8     }
 9 
10     enum Dessert implements Food {
11         TIRAMISU, GELATO, BLACK_fOREST_CAKE, FRUIT;
12     }
13 
14     enum Coffee implements Food {
15         BLACK_COFFEE, DECAF_COFFEE, LATTE;
16     }
17 }

     对于enum而言,实现接口是使其子类化的唯一办法。通过上面的形式,成功的对不同的食物进行分组,但都是Food。 

 

枚举的枚举

     下面是一个枚举的随机选择器,是一个工具类。

 1 public class Enums {
 2     private static Random rand = new Random(47);
 3 
 4     public static <T extends Enum<T>> T randrom(Class<T> ec) {
 5         return random(ec.getEnumConstants());
 6     }
 7 
 8     public static <T> T random(T[] values) {
 9         return values[rand.nextInt(values.length)];
10     }
11 }

     结合工具类及上面Food接口的内容,下面使用枚举的枚举实现一个产生随机菜单的例子。

 1 public enum Course {
 2     APPETIZER(Food.Appetizer.class), MAINCOURSE(Food.MainCourse.class), DESSERT(
 3             Food.Dessert.class), COFFEE(Food.Coffee.class);
 4     private Food[] values;
 5 
 6     private Course(Class<? extends Food> kind) {
 7         // 返回枚举中所有的元素,及所有实例构成的数组,如果kind不是枚举返回null
 8         values = kind.getEnumConstants();
 9     }
10 
11     public Food randomSelection() {
12         return Enums.random(values);
13     }
14 
15     public static void main(String[] args) {
16         // 产生5份随机菜单
17         for (int i = 0; i < 5; i++) {
18             for (Course c : Course.values()) {
19                 Food food = c.randomSelection();
20                 System.out.println(food);
21             }
22             System.out.println("--------------------");
23         }
24     }
25 }

     下面给出一个验证values()方法不是通过父类继承的方法。

 1 public enum Signal implements ObjectDescription {
 2     Red("红灯", "敢过去就是6分,还要罚款哦"), Yellow("黄灯", "黄灯你也不敢过"), Green("绿灯", "绿灯也得小心过啊");
 3 
 4     private String name;
 5     private String description;
 6 
 7     private Signal(String name, String description) {
 8         this.name = name;
 9         this.description = description;
10     }
11 
12     private String getName() {
13         return name;
14     }
15 
16     private String getDescription() {
17         return description;
18     }
19 
20     @Override
21     public String todo() {
22         return "Signal类用于表示交通信号指示灯," + this + "用于表示" + this.getName();
23     }
24 
25     public static void main(String[] args) {
26         Set<Method> methodSet = new HashSet<Method>();
27         Method[] signalMethods = Signal.class.getMethods();
28         for (Method m : signalMethods) {
29             methodSet.add(m);
30         }
31         Method[] superClassMethods = Signal.class.getSuperclass().getMethods();
32         for (Method m : superClassMethods) {
33             methodSet.remove(m);
34         }
35         System.out.println(methodSet);
36     }
37 
38 }

 

如果本文对您有帮助,点一下右下角的“推荐”
目录
相关文章
|
1月前
|
安全 Java 测试技术
🎉Java零基础:全面解析枚举的强大功能
【10月更文挑战第19天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
121 60
|
28天前
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
50 24
|
3月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
77 9
Java——反射&枚举
|
3月前
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
93 5
|
3月前
|
安全 Java 开发者
Java 枚举(enum)详解
Java 中的枚举(`enum`)是一种特殊的数据类型,用于定义一组固定的常量,提升代码的类型安全性和可读性。枚举使用 `enum` 关键字定义,支持方法和构造函数,具有类型安全、单例、自动序列化等特点,并且可以遍历和用于 `switch` 语句中。实际应用包括状态机、指令集、类型标识等场景。枚举使代码更加清晰易维护。
248 1
|
4月前
|
Java
Java枚举使用的基本案例
这篇文章是关于Java枚举的基本使用,通过一个指令下发的代码案例,展示了如何定义枚举、使用枚举以及如何通过枚举实现指令的匹配和处理。
|
4月前
|
Java 开发者
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案。本文通过技术综述及示例代码,剖析两者在性能上的差异。if-else具有短路特性,但条件增多时JVM会优化提升性能;switch则利用跳转表机制,在处理大量固定选项时表现出色。通过实验对比可见,switch在重复case值处理上通常更快。尽管如此,选择时还需兼顾代码的可读性和维护性。理解这些细节有助于开发者编写出既高效又优雅的Java代码。
66 2
|
4月前
|
安全 Java 编译器
|
5月前
|
存储 缓存 Java
java枚举消除冗余代码问题之findByName和findByValue方法工作时的问题如何解决
java枚举消除冗余代码问题之findByName和findByValue方法工作时的问题如何解决
|
5月前
|
安全 Java
Java进阶之枚举
【7月更文挑战第11天】Java枚举是Java 5引入的特性,用于定义固定常量集合,如星期。枚举是继承自`java.lang.Enum`的特殊类,编译后成为final类,每个枚举值是静态final实例。定义枚举用`enum`关键字,如`public enum Weekday {MONDAY, TUESDAY, ...}`。枚举可包含方法和变量,能实现接口但不能继承其他类。例如,`Weekday`枚举可实现`Describe`接口,提供`describe()`方法。在实际应用中,枚举常用于表示如响应状态等固定选项,便于类型安全和代码阅读。
46 8