JAVA Enum枚举类详解

在一些情况下,一个类的对象是有限且固定的,如季节类,只有春夏秋冬4个对象,这种实例有限且固定的类,在JAVA里称为枚举类。

 

1.手动实现枚举类

采用的设计方式:

通过private将构造器隐藏起来

把这个类所有可能的实例都使用public static final修饰的类变量来保存

 

首先定义一个Season

public class Season{

private final String name;

private final String desc;

public static final Season SPRING

=new Season("春天","趁春踏青");

public static final Season SUMMER

=new Season("夏天","夏日炎炎");

public static final Season FALL

=new Season("秋天","秋高气爽");

public static final Season WINTER

=new Season("冬天","围炉赏雪");

public String getName() {

return name;

}

public String getDesc() {

return desc;

}

public Season(String name, String desc) {

super();

this.name = name;

this.desc = desc;

}

}

 

public class SeasonTest {

public SeasonTest(Season s){

System.out.println(s.getName()+" "+s.getDesc());

}

public static void main(String[] args){

new SeasonTest(Season.FALL);

}

}

 

从上面程序不难看出,使用枚举类可以使程序更加健壮,避免对象的随意性,在更早前,程序员还喜欢使用简单的静态常量来表示:

如  public static final int SEASON_PRING=1;

虽然简单明了,但存在几点问题:

类型不安全,因为是int类型,当当成整数计算时也不会出错

没有命名空间,容易和其他变量混淆

打印输出不明确,输出1很难联想到春天

 

 

 

2.为了更好处理实例固定的类,JAVA5新增了Enum关键字(它与classinterface地位相同),用于定义枚举类。

枚举类与普通类的区别:

使用enum定义的非抽象的枚举类默认使用final修饰,因此不能派生子类

构造器只能用private修饰,默认也是private

枚举类的所有实例必须在枚举类的第一行显示列出,否则这个枚举类永远不能产生实例,列出的实例默认会使用public static final修饰

格式如下:

public enum Color{

YELLOW,BLUE,GREEN;

}

编译上面的程序,将生成一个Color.class文件,表面Enum是一个特殊的JAVA文件,枚举值以逗号隔开,分号结束

测试:

public class Test{

public static void main(String[] args) {

//所有枚举类都有一个values方法,返回该枚举类的所有实例

for(Color c : Color.values()){

switch(c){

case YELLOW:  System.out.println("yellow");break;

case BLUE:    System.out.println("blue"); break;

case GREEN:   System.out.println("green"); break;

}

}

}

}

 

枚举类其他常用方法:

int compareTo(E o)           ----------      比较此枚举与指定对象的顺序

String toString()          ----------     返回枚举常量的名称

int ordinal()              ----------     返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零

(其余方法详见API)

3.枚举类的Field、方法、构造器

枚举类也可以定义Filed,方法,如:

public enum Gender {

MALE,FEMALE;

private String name;


public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

public class GenderTest {

public static void main(String[] args) {

//通过EnumvalueOf方法来或取指定枚举类的枚举值

Gender g  = Enum.valueOf(Gender.class,"FEMALE");

//直接为枚举值的Field赋值

g.setName("");

//输出

System.out.println(g+","+g.getName());

}

}

输出:FEMALE,

 

需要注意一点,枚举类的实例只能是枚举值,而不是随意通过new来创建枚举类对象。

实际上枚举类通常被设计为不可变类,它的Field不应该允许改变,Filed最好使用private final修饰,如:

 

public enum Gender {

MALE(""),FEMALE("");

private final String name;


private Gender(String name) {

this.name = name;

}

public String getName() {

return name;

}

}

public class GenderTest {

public static void main(String[] args) {

//直接输出

System.out.println(Gender.MALE+","+Gender.MALE.getName());

//通过EnumvalueOf方法来或取指定枚举类的枚举值

Gender g  = Enum.valueOf(Gender.class,"FEMALE");

//输出

System.out.println(g+","+g.getName());

}

}

输出:MALE,男

FEMALE,女

 

4.实现接口的枚举类

枚举类也可以像其他类一样实现接口,如:

public interface GenderDesc {

void info();

}

public enum Gender implements GenderDesc{

//...与上面相同

@Override

public void info() {

System.out.println("这是一个用于定义性别的枚举类");

}

}

虽然实现了接口,但每个枚举值在调用该方法时都实现了相同的行为方式,如果需要不同的行为方式,可以使用下面做法:

public enum Gender implements GenderDesc{

MALE(""){

public void info(){

System.out.println("此枚举值代表男性");

}

},

FEMALE(""){

public void info(){

System.out.println("此枚举值代表女性");

}

};

private final String name;

private Gender(String name) {

this.name = name;

}

public String getName() {

return name;

}

@Override

public void info() {

System.out.println("这是一个用于定义性别的枚举类");

}

}

 

public class GenderTest {

public static void main(String[] args) {

//输出

Gender.FEMALE.info();

Gender.MALE.info();

}

}

 

输出: 此枚举值代表女性

     此枚举值代表男性

 

从输出可以看出,优先调用自身实现的行为方式,没有时枚举值才会调用公共方式。

上面的花括号其实是一个匿名内部类的类体部分,在使用花括号情况下,当创建MALE,FEMALE枚举值时,并不是直接创建Gender枚举类的实例,而是相当于创建Gender的匿名子类的实例,因为通过编译上面的程序,可以看出生成Gender.class,Gender$1.classGender$2.class三个文件,所以当我们调用MALE,FEMALE的方法时,会表现不同的行为方式。

 

5.包含抽象方法的枚举类

先看一个例子:

public enum Operation {

PLUS{

public double eval(double xdouble y) {

return x+y;

}

},

MINUS{

public double eval(double xdouble y) {

return x-y;

}

},

TIMES{

public double eval(double xdouble y) {

return x*y;

}

},

DIVIDE{

public double eval(double xdouble y) {

return x/y;

}

};

public abstract double eval(double x,double y);

public static void main(String[] args){

System.out.println(Operation.PLUS.eval(3, 4));

System.out.println(Operation.MINUS.eval(3, 4));

System.out.println(Operation.TIMES.eval(3, 4));

System.out.println(Operation.DIVIDE.eval(3, 4));

}

}

输出:7.0    -1.0   12.0   0.75

在接口那我们提到,在使用花括号情况下创建的是匿名子类的实例,当枚举类定义抽象方法时默认会添加abstract关键字,所以需要在枚举值花括号中进行方法的实现,否则会出现编译错误。

你可能感兴趣的:(java基础)