Java 枚举类详解

1. 枚举类定义html

在某些状况下,一个类的对象是有限并且固定的,好比季节类,它只有4个对象,这种实例有限并且固定的类,在Java里被称为枚举类java

2. 早期实现枚举的方式程序员

public static final int SEASON_SPRING = 1;
public static final int SEASON_SUMMER= 2;
public static final int SEASON_FALL = 3;
public static final int SEASON_WINTER = 4;

这种定义季节的方式简单明了,但存在以下几个问题:api

1)类型不安全:由于上面的每一个季节其实是一个int整数,所以彻底能够把一个季节当成一个int整数使用,例如进行加法运算SEASON_SPRING+SEASON_SUMMER,这种代码彻底正常。安全

2)没有命名空间:当须要使用季节时,必须在SPRING前使用SEASON_前缀,不然程序可能与其它类中的静态常量混淆。微信

3)打印输出的意义不明确:当输出某个季节时,例如输出SEASON_SPRING,实际上输出的是1,这个1很难猜想出它是表明春天的。数据结构

但枚举又确实存在的意义,所以早期也可采用经过定义类的方式来实现,能够采用以下设计方式。测试

1)经过private将构造器隐藏起来。spa

2)把这个类的全部可能实例都使用public static final修饰的类变量来保存。.net

3)若是有必要,能够提供一些静态方法,容许其余程序根据特定参数来获取与之匹配的实例。

4)使用枚举类可使程序更加健壮,避免建立对象的随意性。

但经过定义类来实现枚举的代码量比较大,实现起来比较麻烦,Java从JDK1.5后就增长了对枚举类的支持。

3. 枚举类详解

Java5新增了一个enum关键字(它与class、interface关键字的地位相同),用以定义枚举类。正如前面看到的,枚举类是一个特殊的类,它同样能够有本身的成员变量、方法,能够实现一个或者多个接口,也能够定义本身的构造器。一个Java源文件中最多只能定义一个public访问权限的枚举类,且该Java源文件也必须和该枚举类的类名相同。

但枚举类终究不是普通的类,它与普通类有以下区别:

1)枚举类不能显示继承其它类,枚举类能够实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是默认继承Object类。其中Enum类实现了Serializable和Comparable两个接口。

2)枚举类不能派生子类,使用enum定义、非抽象的枚举类默认会使用final修饰。

3)枚举类的构造器只能使用private访问控制符,若是省略了构造器的访问控制符,则默认使用private修饰。

4)枚举类的实例必须在枚举类的第一行显示列出,不然这个枚举类永远都不能产生实例。列出这些实例时,系统会自动添加public static final修饰,无需程序员显示添加。

枚举类默认提供了一个values()方法,该方法能够很方便的遍历全部枚举值。

下面程序定义了一个SeasonEnum枚举类

public enum SeaonEnum{
  //在第一行列出4个枚举实例
  SPRING,SUMMER,FALL,WINTER;  
}

定义枚举类时必须显示的列出全部的枚举值,枚举值之间使用英文逗号隔开,以英文分号结束。

若是须要使用该枚举类的某个实例,则可使用类名.变量名的形式,如SeaonEnum.SPRING。

看下面程序实例:

public class EnumTest{
  public void judge(SeasonEnum s)
    //switch语句里的表达式能够是枚举值
    switch(s){
      case SPRING:
      System.out.println("春暖花开,正好踏青");
      break;
    case SUMMER:
      System.out.println("夏日炎炎,适合游泳");
      break;
    case FALL:
      System.out.println("秋高气爽,及时进补");
      break;
    case WINTER:
      System.out.println("冬日飘雪,围炉赏雪");
      break;
    }
  }
  public static void main(String[] args){
    //枚举类默认有一个values()方法,返回该枚举类的全部实例
    for(SeasonEnum s : SeasonEnum.values()){
      System.out.println(s);  
    }
    //使用枚举实例时,可经过EnumClass.variable形式来访问
    new EnumTest().judge(SeasonEnum.SPRING);
  }
}

 上面程序测试了SeasonEnum枚举类的用法,该类经过values()方法返回了SeasonEnum枚举类的全部实例,并经过循环迭代输出了SeasonEnum枚举类的全部实例。

因为全部的枚举类都继承了java.lang.Enum类,因此枚举类能够直接使用java.lang.Enum类中所包含的方法。java.lang.Enum类中提供了以下几个方法。

1)int compareTo(E o):比较此枚举与指定对象的顺序。在该对象小于、等于或大于指定对象时,分别返回负整数、零或正整数。 枚举常量只能与相同枚举类型的其余枚举常量进行比较。该方法实现的天然顺序就是声明常量的顺序。

2)String name():返回此枚举常量的名称,在其枚举声明中对其进行声明。 与此方法相比,大多数程序员应该优先考虑使用toString()方法,由于 toString 方法返回更加用户友好的名称。该方法主要设计用于特殊情形,其正确性取决于获取正确的名称,其名称不会随版本的改变而改变。

3) int ordinal():返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。 大多数程序员不会使用此方法。它被设计用于复杂的基于枚举的数据结构,好比 EnumSet 和 EnumMap

4)String toString():返回枚举常量的名称,它包含在声明中。能够重写此方法,虽然通常来讲没有必要。当存在更加“程序员友好的”字符串形式时,应该使用枚举类型重写此方法。

5)public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name):返回带指定名称的指定枚举类型的枚举常量。名称必须与在此类型中声明枚举常量所用的标识符彻底匹配。(不容许使用额外的空白字符。)

正如前面看到的,当程序使用System.out.println(s)语句来打印枚举值时,实际上输出的是该枚举值得toString()方法,也就是输出该枚举值的名字。

 

欢迎关注微信公众号【Java典籍】,收看更多Java技术干货!

  ▼微信扫一扫下图↓↓↓二维码关注

 

相关文章
相关标签/搜索