• 枚举


    语法(定义)
    创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式 Class Enum<E extends Enum>,而 E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。
    package com.hmw.test;
    /**

    • 枚举测试类

    • @author 汝妮娑鸢
      */
      public enum EnumTest {
      MON, TUE, WED, THU, FRI, SAT, SUN;
      }
      这段代码实际上调用了7次 Enum(String name, int ordinal):
      new Enum("MON",0);
      new Enum("TUE",1);
      new Enum("WED",2);
      ... ...
      遍历、switch 等常用操作
      对enum进行遍历和switch的操作示例代码:
      public class Test {
      public static void main(String[] args) {
      for (EnumTest e : EnumTest.values()) {
      System.out.println(e.toString());
      }

       System.out.println("----------------我是分隔线------------------");
        
       EnumTest test = EnumTest.TUE;
       switch (test) {
       case MON:
           System.out.println("今天是星期一");
           break;
       case TUE:
           System.out.println("今天是星期二");
           break;
       // ... ...
       default:
           System.out.println(test);
           break;
       }
      

      }
      }
      输出结果:
      MON
      TUE
      WED
      THU
      FRI
      SAT
      SUN
      ----------------我是分隔线------------------
      今天是星期二
      enum 对象的常用方法介绍
      int compareTo(E o)
      比较此枚举与指定对象的顺序。
      Class getDeclaringClass()
      返回与此枚举常量的枚举类型相对应的 Class 对象。
      String name()
      返回此枚举常量的名称,在其枚举声明中对其进行声明。
      int ordinal()
      返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
      String toString()
      返回枚举常量的名称,它包含在声明中。
      static <T extends Enum> T valueOf(Class enumType, String name)
      返回带指定名称的指定枚举类型的枚举常量。
      public class Test {
      public static void main(String[] args) {
      EnumTest test = EnumTest.TUE;

       //compareTo(E o)
       switch (test.compareTo(EnumTest.MON)) {
       case -1:
           System.out.println("TUE 在 MON 之前");
           break;
       case 1:
           System.out.println("TUE 在 MON 之后");
           break;
       default:
           System.out.println("TUE 与 MON 在同一位置");
           break;
       }
        
       //getDeclaringClass()
       System.out.println("getDeclaringClass(): " + test.getDeclaringClass().getName());
        
       //name() 和  toString()
       System.out.println("name(): " + test.name());
       System.out.println("toString(): " + test.toString());
        
       //ordinal(), 返回值是从 0 开始
       System.out.println("ordinal(): " + test.ordinal());
      

      }
      }
      输出结果:
      TUE 在 MON 之后
      getDeclaringClass(): com.hmw.test.EnumTest
      name(): TUE
      toString(): TUE
      ordinal(): 1
      给 enum 自定义属性和方法
      给 enum 对象加一下 value 的属性和 getValue() 的方法:
      package com.hmw.test;

    /**

    • 枚举测试类

    • @author 汝妮娑鸢
      */
      public enum EnumTest {
      MON(1), TUE(2), WED(3), THU(4), FRI(5), SAT(6) {
      @Override
      public boolean isRest() {
      return true;
      }
      },
      SUN(0) {
      @Override
      public boolean isRest() {
      return true;
      }
      };

      private int value;

      private EnumTest(int value) {
      this.value = value;
      }

      public int getValue() {
      return value;
      }

      public boolean isRest() {
      return false;
      }
      }
      public class Test {
      public static void main(String[] args) {
      System.out.println("EnumTest.FRI 的 value = " + EnumTest.FRI.getValue());
      }
      }
      输出结果:
      EnumTest.FRI 的 value = 5
      EnumSet,EnumMap 的应用
      public class Test {
      public static void main(String[] args) {
      // EnumSet的使用
      EnumSet weekSet = EnumSet.allOf(EnumTest.class);
      for (EnumTest day : weekSet) {
      System.out.println(day);
      }

       // EnumMap的使用
       EnumMap<EnumTest, String> weekMap = new EnumMap(EnumTest.class);
       weekMap.put(EnumTest.MON, "星期一");
       weekMap.put(EnumTest.TUE, "星期二");
       // ... ...
       for (Iterator<Entry<EnumTest, String>> iter = weekMap.entrySet().iterator(); iter.hasNext();) {
           Entry<EnumTest, String> entry = iter.next();
           System.out.println(entry.getKey().name() + ":" + entry.getValue());
       }
      

      }
      }
      原理分析
      enum 的语法结构尽管和 class 的语法不一样,但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum。EnumTest 经过反编译(javap com.hmw.test.EnumTest 命令)之后得到的内容如下:
      public class com.hmw.test.EnumTest extends java.lang.Enum{
      public static final com.hmw.test.EnumTest MON;
      public static final com.hmw.test.EnumTest TUE;
      public static final com.hmw.test.EnumTest WED;
      public static final com.hmw.test.EnumTest THU;
      public static final com.hmw.test.EnumTest FRI;
      public static final com.hmw.test.EnumTest SAT;
      public static final com.hmw.test.EnumTest SUN;
      static {};
      public int getValue();
      public boolean isRest();
      public static com.hmw.test.EnumTest[] values();
      public static com.hmw.test.EnumTest valueOf(java.lang.String);
      com.hmw.test.EnumTest(java.lang.String, int, int, com.hmw.test.EnumTest);
      }
      所以,实际上 enum 就是一个 class,只不过 java 编译器帮我们做了语法的解析和编译而已。
      总结
      可以把 enum 看成是一个普通的 class,它们都可以定义一些属性和方法,不同之处是:enum 不能使用 extends 关键字继承其他类,因为 enum 已经继承了 java.lang.Enum(java是单一继承)。

    ---------------------------------------------------Ⅱ---------------------------------------------------------------

    一:Enum 类型的介绍
      枚举类型(Enumerated Type) 很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中。而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常量的定义相似。不过相比较常量类型,枚举类型可以为申明的变量提供更大的取值范围。
    二:Enum 类型的特点
    在某些情况下,一个类的对象时有限且固定的,如季节类,它只有春夏秋冬4个对象这种实例有限且固定的类,在 Java 中被称为枚举类;
    在 Java 中使用 enum 关键字来定义枚举类,其地位与 class、interface 相同;
    枚举类是一种特殊的类,它和普通的类一样,有自己的成员变量、成员方法、构造器 (只能使用 private 访问修饰符,所以无法从外部调用构造器,构造器只在构造枚举值时被调用);
    一个 Java 源文件中最多只能有一个 public 类型的枚举类,且该 Java 源文件的名字也必须和该枚举类的类名相同,这点和类是相同的;
    使用 enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Seriablizable 和 java.lang.Comparable 两个接口;
    所有的枚举值都是 public static final 的,且非抽象的枚举类不能再派生子类;
    枚举类的所有实例(枚举值)必须在枚举类的第一行显式地列出,否则这个枚举类将永远不能产生实例。列出这些实例(枚举值)时,系统会自动添加 public static final 修饰,无需程序员显式添加。
    三:Enum 使用

    package com.ljq.test;

    /**

    • 枚举用法详解

    • @author 汝妮娑鸢
      /
      public class TestEnum {
      /
      *

      • 普通枚举
      • @author 汝妮娑鸢

      */
      public enum ColorEnum {
      red, green, yellow, blue;
      }

      /**

      • 枚举像普通的类一样可以添加属性和方法,可以为它添加静态和非静态的属性或方法
      • @author 汝妮娑鸢

      */
      public enum SeasonEnum {
      //注:枚举写在最前面,否则编译出错
      spring, summer, autumn, winter;

       private final static String position = "test";
      
       public static SeasonEnum getSeason() {
           if ("test".equals(position))
               return spring;
           else
               return winter;
       }
      

      }

      /**

      • 性别
      • 实现带有构造器的枚举
      • @author 汝妮娑鸢

      */
      public enum Gender{
      //通过括号赋值,而且必须带有一个参构造器和一个属性跟方法,否则编译出错
      //赋值必须都赋值或都不赋值,不能一部分赋值一部分不赋值;如果不赋值则不能写构造器,赋值编译也出错
      MAN("MAN"), WOMEN("WOMEN");

       private final String value;
      
       //构造器默认也只能是private, 从而保证构造函数只能在内部使用
       Gender(String value) {
           this.value = value;
       }
       
       public String getValue() {
           return value;
       }
      

      }

      /**

      • 订单状态
      • 实现带有抽象方法的枚举
      • @author 汝妮娑鸢

      /
      public enum OrderState {
      /
      * 已取消 /
      CANCEL {public String getName(){return "已取消";}},
      /
      * 待审核 /
      WAITCONFIRM {public String getName(){return "待审核";}},
      /
      * 等待付款 /
      WAITPAYMENT {public String getName(){return "等待付款";}},
      /
      * 正在配货 /
      ADMEASUREPRODUCT {public String getName(){return "正在配货";}},
      /
      * 等待发货 /
      WAITDELIVER {public String getName(){return "等待发货";}},
      /
      * 已发货 /
      DELIVERED {public String getName(){return "已发货";}},
      /
      * 已收货 */
      RECEIVED {public String getName(){return "已收货";}};

       public abstract String getName();
      

      }

      public static void main(String[] args) {
      //枚举是一种类型,用于定义变量,以限制变量的赋值;赋值时通过“枚举名.值”取得枚举中的值
      ColorEnum colorEnum = ColorEnum.blue;
      switch (colorEnum) {
      case red:
      System.out.println("color is red");
      break;
      case green:
      System.out.println("color is green");
      break;
      case yellow:
      System.out.println("color is yellow");
      break;
      case blue:
      System.out.println("color is blue");
      break;
      }

       //遍历枚举
       System.out.println("遍历ColorEnum枚举中的值");
       for(ColorEnum color : ColorEnum.values()){
           System.out.println(color);
       }
       
       //获取枚举的个数
       System.out.println("ColorEnum枚举中的值有"+ColorEnum.values().length+"个");
       
       //获取枚举的索引位置,默认从0开始
       System.out.println(ColorEnum.red.ordinal());//0
       System.out.println(ColorEnum.green.ordinal());//1
       System.out.println(ColorEnum.yellow.ordinal());//2
       System.out.println(ColorEnum.blue.ordinal());//3
       
       //枚举默认实现了java.lang.Comparable接口
       System.out.println(ColorEnum.red.compareTo(ColorEnum.green));//-1
       
       //--------------------------
       System.out.println("===========");
       System.err.println("季节为" + SeasonEnum.getSeason());
       
       
       //--------------
       System.out.println("===========");
       for(Gender gender : Gender.values()){
           System.out.println(gender.value);
       }
      
       //--------------
       System.out.println("===========");
       for(OrderState order : OrderState.values()){
           System.out.println(order.getName());
       }
      

      }

    }

    四:枚举集合的使用

    java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型
    JDK5.0 中在增加 Enum 类的同时,也增加了两个工具类 EnumSet 和 EnumMap,这两个类都放在 java.util 包中。EnumSet 是一个针对枚举类型的高性能的 Set 接口实现。EnumSet 中装入的所有枚举对象都必须是同一种类型,在其内部,是通过 bit-vector 来实现,也就是通过一个 long 型数。EnumSet 支持在枚举类型的所有值的某个范围中进行迭代。

    enum WeekDayEnum { Mon, Tue, Wed, Thu, Fri, Sat, Sun }
    你能够在每周七天日期中进行迭代,EnumSet 类提供一个静态方法 range 让迭代很容易完成:

    for(WeekDayEnum day : EnumSet.range(WeekDayEnum.Mon, WeekDayEnum.Fri)) {
    System.out.println(day);
    }
    打印结果如下:

    Mon
    Tue
    Wed
    Thu
    Fri
    EnumSet 还提供了很多个类型安全的获取子集的 of 方法,很容易取得子集:

    EnumSet subset = EnumSet.of(WeekDayEnum.Mon, WeekDayEnum.Wed);
    for (WeekDayEnum day : subset) {
    System.out.println(day);
    }
    打印结果如下:

    Mon
    Wed

    与 EnumSet 类似,EnumMap 也是一个高性能的 Map 接口实现,用来管理使用枚举类型作为 keys 的映射表,内部是通过数组方式来实现。EnumMap 将丰富的和安全的 Map 接口与数组快速访问结合到一起,如果你希望要将一个枚举类型映射到一个值,你应该使用 EnumMap。看下面的例子:

    // 定义一个 EnumMap 对象,映射表主键是日期枚举类型,值是颜色枚举类型
    private static Map<WeekDayEnum, RainbowColor> schema =
    new EnumMap<WeekDayEnum, RainbowColor>(WeekDayEnum.class);

    static{
    // 将一周的每一天与彩虹的某一种色彩映射起来
    for (int i = 0; i < WeekDayEnum.values().length; i++) {
    schema.put(WeekDayEnum.values()[i], RainbowColor.values()[i]);
    }
    }
    System.out.println("What is the lucky color today?");
    System.out.println("It's " + schema.get(WeekDayEnum.Sat));


    1、枚举类在经过编译后确实是生成了一个扩展了java.lang.Enum的类
    2、枚举类是final的,因此我们无法再继承它了
    3、我们定义的每个枚举值都是该类中的一个成员,且成员的类型仍然是Season类型
    4、枚举类中被默认增加了许多静态方法,例如values()、valuesOf()等

  • 相关阅读:
    ThinkPHP 3.2.2 实现持久登录 ( 记住我 )
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 20 有效的括号
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 19删除链表的倒数第N个节点
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 18 四数之和
    Java实现 LeetCode 17 电话号码的字母组合
  • 原文地址:https://www.cnblogs.com/miniSimple/p/12291304.html
Copyright © 2020-2023  润新知