Java中的枚举类型学习

一:枚举的引入

  enum全称enumeration,是JDK1.5中引入的新特性,存放在java.lang包中。下面就平时的学习和使用过程中用到的进行总结:

  枚举(enum),是指一个经过排序的,被打包成一个单一实体的项列表。一个枚举的实例可以使用枚举项列表中任意单一项的值。枚举在各个语言当中都有着广泛的应用,通常用来表示颜色,方式,类别,状态等等数目有限,形式离散,表达又极为明确的量。所以Java从JDK1.5之后,引入了对枚举的支持。

  那么在枚举出现之前,如果想表示一组特定的离散值,往往使用一些常量。例如:

package com.java.mbt.netty;

public class EntityTool {
    public static final int VIDEO=1;
    public static final int AUDIO=1;
    public static final int IMAGE=1;
    public static final int TEXT=1;

    private int id=0;
    private int type=0;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }
}

当然,常量也不仅仅局限于int型,诸如char和String等也是不在少数。然而,无论使用什么样的类型,这样做都有很多的坏处。这些常量通常都是连续、有无穷多个值的量,而类似这种表示类别的量则是离散的,并且通常情况下只有有限个值。用连续的量去表示离散量,会产生很多问题。例如,针对上述的Entity类,如果要对Entity对象的type属性进行赋值,一般会采用如下方法:

package com.java.mbt.netty;

public class NettyServer {
    public void test(){
        EntityTool et=new EntityTool();
        et.setId(10);
        et.setType(2);
    }
}

这样做的缺点有:(1)代码可读性差、易用性低。由于setType()方法的参数是int型的,在阅读代码的时候往往会让读者感到一头雾水,根本不明白这个2到底是什么意思,代表的是什么类型。当然,要保证可读性,还有这样一个办法:

package com.java.mbt.netty;

public class NettyServer {
    public void test(){
        EntityTool et=new EntityTool();
//        et.setId(10);
//        et.setType(2);

        et.setId(1);
        et.setType(EntityTool.AUDIO);
    }
}

而这样的话,问题又来了。这样做,客户端必须对这些常量去建立理解,才能了解如何去使用这个东西。说白了,在调用的时候,如果用户不到Entity类中去看看,还真不知道这个参数应该怎么传、怎么调。像是setType(2)这种用法也是在所难免,因为它完全合法,不是每个人都能够建立起用常量名代替数值,从而增加程序可读性、降低耦合性的意识。

  (2)类型不安全。在用户去调用的时候,必须保证类型完全一致,同时取值范围也要正确。像是setType(-1)这样的调用是合法的,但它并不合理,今后会为程序带来种种问题。也许你会说,加一个有效性验证嘛,但是,这样做的话,又会引出下面的第(3)个问题。

  (3)耦合性高,扩展性差。假如,因为某些原因,需要修改Entity类中常量的值,那么,所有用到这些常量的代码也就都需要修改——当然,要仔细地修改,万一漏了一个,那可不是开玩笑的。同时,这样做也不利于扩展。例如,假如针对类别做了一个有效性验证,如果类别增加了或者有所变动,则有效性验证也需要做对应的修改,不利于后期维护。

  枚举就是为了这样的问题而诞生的。它们给出了将一个任意项同另一个项相比较的能力,并且可以在一个已定义项列表中进行迭代。枚举(在Jave中简称为enum)是一个特定类型的类。所有枚举都是Java中的新类java.lang.Enum的隐式子类。此类不能手工进行子类定义。一个简单的枚举可以是这样:

package com.java.mbt.netty;

public enum Entity {
    VIDEO,AUDIO,IMAGE,TEXT
}
package com.java.mbt.netty;

public class EntityH {
    private int id=0;
    private Entity type;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Entity getType() {
        return type;
    }

    public void setType(Entity type) {
        this.type = type;
    }
}

在为Entity对象赋值的时候,就可以这样:

package com.java.mbt.netty;

public class NettyServer {
    public void test(){
//        EntityTool et=new EntityTool();
////        et.setId(10);
////        et.setType(2);
//
//        et.setId(1);
//        et.setType(EntityTool.AUDIO);

        EntityH eh=new EntityH();
        eh.setId(1);
        eh.setType(Entity.AUDIO);
    }
}

怎么看,都是好了很多。在调用setType()时,可选值只有四个,否则会出现编译错误,因此可以看出,枚举是类型安全的,不会出现取值范围错误的问题。同时,客户端不需要建立对枚举中常量值的了解,使用起来很方便,并且可以容易地对枚举进行修改,而无需修改客户端。如果常量从枚举中被删除了,那么客户端将会失败并且将会收到一个错误消息。枚举中的常量名称可以被打印,因此除了仅仅得到列表中项的序号外还可以获取更多信息。

 

二:枚举的语法定义

    创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式 Class Enum<E extends Enum<E>>,而 E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。

Java中的枚举类型学习

Java中的枚举类型学习