Java 进阶(16)枚举

概念

枚举类型是Java 5中新增特性的⼀部分,它是⼀种特殊的数据类型,之所以特殊是因为它既是⼀种类(class)类型却⼜⽐类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。

枚举在各个语⾔当中都有着⼴泛的应⽤,通常⽤来表示诸如颜⾊、⽅式、类别、状态等等数⽬有限、形式离散、表达⼜极为明确的量。Java从JDK5开始,引⼊了对枚举的⽀持。

为什么使用枚举

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

public class Entity {
    public static final int VIDEO = 1;//视频
    public static final int AUDIO = 2;//⾳频
    public static final int TEXT = 3;//⽂字
    public static final int IMAGE = 4;//图⽚
    
    private int id;
    private int type;
    
    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;
    }
}

例如,针对上述的Entity类,如果要对Entity对象的type属性进⾏赋值,⼀般会采⽤如下方法:

Entity e = new Entity();
e.setId(10);
//e.setType(2);
//⽽这样的话,问题⼜来了。这样做,客户端必须对这些常量去建⽴理解,才能了解如何去使⽤这个东⻄。
//说⽩了,在调⽤的时候,如果⽤户不到Entity类中去看看,还真不知道这个参数应该怎么传、怎么调
e.setType(Entity.AUDIO);

这样做的缺点有:

(1)代码可读性差、易⽤性低。由于setType()⽅法的参数是int型的,在阅读代码的时候往往会让读者感到⼀头雾⽔,根本不明⽩这个2到底是什么意思,代表的是什么类型。

(2)类型不安全。在⽤户去调⽤的时候,必须保证类型完全⼀致,同时取值范围也要正确。像是setType(-1)这样的调⽤是合法的,但它并不合理,今后会为程序带来种种问题。

(3)耦合性⾼,扩展性差。假如,因为某些原因,需要修改Entity类中常量的值,那么,所有⽤到这些常量的代码也就都需要修改——当然,要仔细地修改,万⼀漏了⼀个,那可不是开玩笑的。同时,这样做也不利于扩展。

使用枚举

枚举(在Jave中简称为enum)是⼀个特定类型的类。所有枚举都是Java中的新类

java.lang.Enum的隐式⼦类。此类不能⼿⼯进⾏⼦类定义。⼀个简单的枚举可以是这样:

public enum TypeEnum {
    VIDEO,AUDIO,TEXT,IMAGE;
}

上⾯的Entity类就可以改成这样:

public class Entity2 {
    private int id;
    private TypeEnum type;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public TypeEnum getType() {
        return type;
    }
    public void setType(TypeEnum type) {
        this.type = type;
    }
}

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

Entity2 e = new Entity2();
e.setId(10);
e.setType(TypeEnum.AUDIO);

在调⽤setType()时,可选值只有四个,否则会出现编译错误,因此可以看出,枚举是类型安全的,不会出现取值范围错误的问题。同时,客户端不需要建⽴对枚举中常量值的了解,使⽤起来很⽅便,并且可以容易地对枚举进⾏修改,⽽⽆需修改客户端。如果常量从枚举中被删除了,那么客户端将会失败并且将会收到⼀个错误消息。

在Java中⼀个枚举就是⼀个类,它也可以有属性和⽅法,并且实现接⼝。只是所有的枚举都继承⾃java.lang.Enum类,因此enum不可以再继承其他的类。

下⾯给出在枚举中声明属性和⽅法的示例:

public enum TypeEnum {
    VIDEO(1), AUDIO(2), TEXT(3), IMAGE(4);
    int value;
    TypeEnum(int value) {
        this.value = value;
    }
    public int getValue() {
        return value;
    }
}

如果要为每个枚举值指定属性,则在枚举中必须声明⼀个参数为属性对应类型的构造⽅法(不能是public)。否则编译器将给出The constructor TypeEnum(int, String) is undefined的错误。在此例中,属性为int型,因此构造⽅法应当为int型。除此之外,还可以为枚举指定多个属性

枚举构造器为什么不能是public?

如果其含有public构造器,那么在类的外部就可以通过这个构造器来新建实例,显然这时实例的数量和值就不固定了,这与定义枚举类的初衷相⽭盾,为了避免这种形象,就对枚举类的构造器默认使⽤private修饰。如果为枚举类的构造器显式指定其它访问控制符,则会编译出错

public enum TypeEnum {
    VIDEO(1, "视频"), AUDIO(2, "⾳频"), TEXT(3, "⽂本"), IMAGE(4, "图像");
    int value;
    String name;
    TypeEnum(int value, String name) {
        this.value = value;
        this.name = name;
    }
    public int getValue() {
        return value;
    }
    public String getName() {
        return name;
    }
}

你可能感兴趣的:(Java,进阶,java,开发语言)