zoukankan      html  css  js  c++  java
  • 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 }
    如果本文对您有帮助,点一下右下角的“推荐”
  • 相关阅读:
    -bash: fork: Cannot allocate memory 问题的处理
    Docker top 命令
    docker常见问题修复方法
    The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
    What's the difference between encoding and charset?
    hexcode of é î Latin-1 Supplement
    炉石Advanced rulebook
    炉石bug反馈
    Sidecar pattern
    SQL JOIN
  • 原文地址:https://www.cnblogs.com/hzmark/p/Enum.html
Copyright © 2011-2022 走看看