• Java枚举类型


         关键字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 }
    如果本文对您有帮助,点一下右下角的“推荐”
  • 相关阅读:
    【JavaP6大纲】Java基础篇:为什么jdk8以后HashMap会使用红黑树优化?
    【JavaP6大纲】Java基础篇:HashMap加载因子为什么是0.75?
    【JavaP6大纲】Zookeeper篇:选举机制
    就是要幸福(1)严于律人
    天真的童年
    闲言碎语话心得垃圾工作
    镜花水月
    就是要幸福(3)言行自由
    五年
    爸爸我给你捂捂手
  • 原文地址:https://www.cnblogs.com/hzmark/p/Enum.html
Copyright © 2020-2023  润新知