Java(7)-枚举

参考:java技术手册

参考:https://blog.csdn.net/testcs_dn/article/details/78604547

 

java有两种特殊形式的类型,在java类型系统中扮演着特定的角色。这两种类型是枚举类 型(enumerated type)和注解类型(annotation type)。

 

本文介绍枚举。

 

一、枚举的定义
枚举是类的变种。

假设我们要定义红、黄、蓝色中颜色的枚举,我们可以使用enum关键字定义这个类型:

public enum PrimaryColor {
  // 实例列表末尾的分号是可选的
  RED, GREEN, BLUE
}

注意:
(1)如上PrimaryColor定义的是一个类型,这个类型是枚举。

(2)枚举内部的REG、GREEN、BLUE实际上是PrimaryColer类型的实例

 

通过如下包含成员的枚举类型定义,更好的理解枚举实例的概念:

  Java中由于枚举是特殊的类,所以可以拥有成员(字段和方法)

  假设,我们要定义一个枚举,包含前几个正多边形(等边等角的形状),而且想为这些形状指定一些属性(在方法中指定)。我们可以使用接收一个参数的枚举实现这个需求,如下所示:

  public enum RegularPolygon {
    // 有参数的枚举必须使用分号。由于这些实际上是RegularPolygon的实例,所以可以传入 “构造方法 参数。
    TRIANGLE(3), SQUARE(4), PENTAGON(5), HEXAGON(6);

    private Shape shape;

    public Shape getShape() {
      return shape;
    }

    private RegularPolygon(int sides) {
      switch (sides) {
        case 3:
          // 假设这些形状的构造方法接收的参数是边长和角度
          shape = new Triangle(1,1,1,60,60,60);
          break;
        case 4:
          shape = new Rectangle(1,1);
          break;
        case 5:
          shape = new Pentagon(1,1,1,1,1,108,108,108,108,108);
          break;
        case 6:
          shape = new Hexagon(1,1,1,1,1,1,120,120,120,120,120,120);
          break;
        }
      }
    }

  注意,如上:

  (1)如果字段或方法有主体,那么实例列表后面必须加上分号。 

  (2)如上样例中,枚举实例(TRIANGLE、SQUARE、PENTAGON、HEXAGON)具有参数,所以要显式提供构造函数。枚举实例由Java运行时创建,在创建TRIANGLE、SQUARE、PENTAGON、HEXAGON实例时,调用RegularPlygon ()构造方法,分别传入2、4、5、6入参,为这几个枚举实例分配内存空间和赋值。本质上每个枚举实例包含一个shape字段和2个方法。

  (3)枚举实例由Java运行时创建,其不可在枚举外部进行实例化,所以把构造方法声明为私有方法

  (4)枚举有如下特殊性:

    • 都(隐式)扩展 java.lang.Enum 类;(所以不可继承其他类)

    • 不能泛型化;

    • 可以实现接口;

    • 不能被扩展子类

    • 只能有一个私有(或使用默认访问权限)的构造方法

    • 所有的枚举值默认都是 public static final 的。

 

二、枚举引入的版本

enum类型是java1.5引入的。

  

三、枚举类型的使用

(1)类似常量的方式使用

  支持枚举之前,常量只能通过public static fianl方式定义。

       引入枚举后,可以使用枚举实现类似常量方式的代码使用。如:

  public enum PrimaryColor {
    // 实例列表末尾的分号是可选的
    RED, GREEN, BLUE
  }

       PrimaryColor类型的REG、GREEN、BLUE实例可以按照静态字段的方式引用:PrimaryColor.RED、PrimaryColor. GREEN 和 PrimaryColor.BLUE。

 

(2)配合switch使用
      如:

  enum Signal {
    GREEN, YELLOW, RED
  }


  public class TrafficLight {
    Signal color = Signal.RED;
    

    public void change() {
      switch (color) {
        case RED:
          color = Signal.GREEN;
          break;
        case YELLOW:
          color = Signal.RED;
          break;
        case GREEN:
          color = Signal.YELLOW;
          break;
      }
    }
  }

 

 

(3)配合for循环遍历枚举中的实例

  private enum SimpleEnum {
    SPRING, SUMMER, AUTUMN, WINTER
  }

  public class EnumTest {
    /**
    * 循环枚举,输出ordinal属性;若枚举有内部属性,则也输出。(说的就是我定义的TYPE类型的枚举的typeName属性)
    */
    private static void forEnum() {
      for (SimpleEnum simpleEnum : SimpleEnum.values()) {
        System.out.println(simpleEnum + " ordinal " + simpleEnum.ordinal());
      }
    }
  }

  打印结果是:

  SPRING ordinal 0

  SUMMER ordinal 1

  AUTUMN ordinal 3

  WINTER ordinal 4

       注:

      (1)如上ordinal是继承自 java.lang.Enum 类的int类型字段

      (2)如上println打印中simpleEnum参数会自动调用java.lang.Enum类型从Object中继承的toString()方法转换。

      (3)Java编译器自动在enum类型中插入一些方法,其中就包括values()。所以在enum类型中并没有实现values()方式,程序在没编译的时候,自然就没法查看values()方法的源码。

 

(4)枚举中自定义方法、和覆盖继承自enum类型的方法

        enum类型本质上是类,可以自定义方法和覆盖继承的方法。

  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;
    }

    

     @Override  

    public String toString() { 

      returnthis.index+"_"+this.name;  

    }  

  }

  public class EnumTest { 

    ......
    private static void forEnum() {
      for (Color color : Color.values()) {
        System.out.println("color = " + color + " color.name = " + color.getName() + " color.index = " + color.getIndex());
      }
    }
    ......
  }

 

(5)枚举实例的比较

 枚举本质上是类型,枚举实例本质上是对象。所以枚举类型对象之间的比较也采用equals方法。但是呢,同class类型对象的不同是,==在class类型的比较中实际上比较的是两个引用是否指向同一对象;==在做枚举类型对象比较时,是比较对象的值是否相等,可替代equals()方法

 

(6)枚举可以通过implements关键字继承接口

      使用方式同class继承接口。

 

(7)枚举集合

       java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。关于这个两个集合可以参考JDK文档。

posted @ 2020-04-26 23:22  小拙  阅读(323)  评论(0)    收藏  举报