zoukankan      html  css  js  c++  java
  • 枚举

    语法(定义)
    创建枚举类型要使用 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()等

  • 相关阅读:
    vue.js 初步学习
    IntelliJ IDEA 快捷键
    SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
    JavaScript基础概念与语法
    python 常见矩阵运算
    利用matplotlib的plot函数实现图像绘制
    基于密度峰值的聚类(DPCA)
    极角排序
    HDU-5514 Frogs (容斥)
    HDU
  • 原文地址:https://www.cnblogs.com/miniSimple/p/12291304.html
Copyright © 2011-2022 走看看