关键词搜索

源码搜索 ×
×

深入学习 Java Enum 枚举类

发布2020-02-19浏览732次

详情内容

Java 有两种方式定义新类型:类和接口。

对于大部分面向对象编程来说,这两种方法够了,但是对于一些特殊情况比如:想定义一个 Color 类,它只能有 Red、Green、Blue 3种值,其他的任何值都是非法的,这种情况就适用枚举简单方便。

所谓的枚举就是限制一个类的对象产生范围
在这里插入图片描述
其他知识可以参考:

一、基本概念

已经知道使用 eunm 关键字可以定义一个枚举,该关键字表示的是 java.lang.Enum类型,即使用 enum 声明的枚举类型就相当于定义一个类,此类默认继承 java.lang.Enum 类。
java.lang.Enum的定义:

public abstract  class Enum<E extends Enum<E>> extends Object
implements Comparable<E>,java.io.Serializable

    从定义可看出该类实现了 Comparable 和 Serializable 接口,证明枚举可以使用比较器和序列化操作

    枚举类的主要操作方法:
    在这里插入图片描述
    枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开

    枚举其实就是特殊的常量类,切构造方法被默认强制是私有
    例如:

    枚举名字:DealStatusEnum
    成员名称:SUCCESS / UNKNOWN_REASON
    

      二、取得枚举的信息

      在枚举类建立完成后,实际上都会为其调用枚举类中的构造方法,为其赋值。在 Enum 类的构造方法中的第一个参数 name 就是定义的枚举的名称,第二个参数 ordinal 则会从 0 开始依次进行编号,之后可以使用 Enum 类总提供的 name()ordinal() 方法取得名称和编号

      enum Color{
          RED,GREEN,BLUE;//定义枚举的3个类型
      }
      public class Test{
          public static void main(String[] args) {
              for (Color c:Color.values()){//枚举.values() 表示得到全部枚举的内容
                  System.out.println(c.ordinal() + "-->" + c.name());
              }
          }
      }
      
        3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      在这里插入图片描述

      三、为每一个枚举对象属性赋值

      如果要为enum定义方法,那么必须在enum的最后一个实例尾部添加一个分号。此外,在enum中,必须先定义实例,不能将字段或方法定义在实例前面。否则,编译器会报错。

      1. 通过构造方法为属性赋值

      每个枚举类中都有其指定好的若干对象,当然每一个枚举对象中也可以包含多个属性,这些属性可以通过构造方法为其赋值

      enum Color{
          RED("红色"),GREEN("绿色"),BLUE("蓝色");//定义枚举的3个类型
          private Color(String name){
              this.setName(name);
          }
          private String name;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
      }
      public class Test{
          public static void main(String[] args) {
              for (Color c:Color.values()){//枚举.values() 表示得到全部枚举的内容
                  System.out.println(c.ordinal() + "-->" + c.name() + c.getName());
              }
          }
      }
      
        3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23

      程序中在定义的 Color 枚举类中设置了一个 name属性,并且通过构造方法设置 name 属性的内容。

      因为 Color 中已经明确地写出了有一个参数的构造方法,所以在声明枚举内容时必须调用这个构造方法,这样在定义枚举内容时必须使用如下的语句形式:

      RED("红色"),GREEN("绿色"),BLUE("蓝色");
      
      • 1

      或者:

      public enum Color {  
          RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
          // 成员变量  
          private String name;  
          private int index;  
          // 构造方法  
          private Color(String name, int index) {  
              this.name = name;  
              this.index = index;  
          }  
          // 普通方法  
          public static String getName(int index) {  
              for (Color c : Color.values()) {  
                  if (c.getIndex() == index) {  
                      return c.name;  
                  }  
              }  
              return null;  
          }  
          // get set 方法  
          public String getName() {  
              return name;  
          }  
          public void setName(String name) {  
              this.name = name;  
          }  
          public int getIndex() {  
              return index;  
          }  
          public void setIndex(int index) {  
              this.index = index;  
          }  
      }  
      
        3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33

      2. 通过 setter方法为属性赋值

      也可以通过调用 setter() 方式为指定的属性赋值,但是这样必须明确每一个枚举类的对象,如果操作的对象时 RED,则名字应该为“红色”;如果操作的对象是GREEN,则名字应该为“绿色”等。

      enum Color{
          RED,GREEN,BLUE;//定义枚举的3个类型
          private String name;
          public String getName(){
              return name;
          }
      
          public void setName(String name) {
              switch (this){
                  case RED:{
                      if ("红色".equals(name)){
                          this.name = name;
                      }else System.out.println("设置内容错误。");
                      break;
                  }
                  case GREEN:{
                      if ("绿色".equals(name)){
                          this.name = name;
                      }else System.out.println("设置内容错误。");
                      break;
                  }
                  case BLUE:{
                      if ("蓝色".equals(name)){
                          this.name = name;
                      }else System.out.println("设置内容错误。");
                      break;
                  }
              }
          }
      }
      public class Root{
          public static void main(String[] args) {
              Color c = Color.BLUE;
              c.setName("兰色");//设置一个错误的名字
              c.setName("蓝色");//设置一个正确的名字
              System.out.println(c.getName());
          }
      }
      
        3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38

      在这里插入图片描述
      代码中首先通过枚举类取得了里面的一个对象,之后开始为期设置内容。

      四、使用比较器

      在 Enum 类的定义中已经实现好了 Comparable 接口,所以枚举类的内容本身是可以进行排序的,可以通过 TreeSet 进行枚举的排序操作

      enum Color {
          RED, GREEN, BLUE;//定义枚举的3个类型
      }
      
      public class Root{
          public static void main(String[] args) {
              Set<Color> t = new TreeSet<Color>();//只能加入 Color 类型
              t.add(Color.GREEN);
              t.add(Color.BLUE);
              t.add(Color.RED);
              Iterator<Color> iter = t.iterator();//使用迭代输出
              while (iter.hasNext()) {
                  System.out.print(iter.next() + "、");
              }
          }
      }
      
        3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      在这里插入图片描述
      这里加入的顺序和输出的信息不一致,证明已经被排序了,是使用Enum 类中的 ordinal 属性排序的

      枚举类型对象之间的值比较,是可以使用==,直接来比较值,是否相等的,不是必须用equals

      五、枚举的原理

      实际上在使用关键字 enum 创建枚举类型并编译后,编译器会为我们生成一个相关的类,这个类继承了Java API中的java.lang.Enum类,

      也就是说通过关键字 enum 创建枚举类型在编译后事实上也是一个类类型而且该类继承自java.lang.Enum类。

      从反编译的代码可以看出编译器确实帮助我们生成了一个Color类而且该类继承自java.lang.Enum类,该类是一个抽象类,
      除此之外,编译器还帮助我们生成了3个Color类型的实例对象分别对应枚举中定义的3个颜色。

      还为我们生成了两个静态方法,分别是values()valueOf()

      到此我们也就明白了,使用关键字enum定义的枚举类型,在编译期后,也将转换成为一个实实在在的类,而在该类中,会存在每个在枚举类型中定义好常量的对应实例对象,如上述的RED枚举类型对应public static final Day RED

      在这里插入图片描述

      相关技术文章

      点击QQ咨询
      开通会员
      返回顶部
      ×
      微信扫码支付
      微信扫码支付
      确定支付下载
      请使用微信描二维码支付
      ×

      提示信息

      ×

      选择支付方式

      • 微信支付
      • 支付宝付款
      确定支付下载