一、什么是枚举?
首先,枚举是一种特殊的类对象,其定义如下:
{修饰符} enum 对象标识 [父接口] 枚举体
枚举类型通过一些特殊的约束,来实现其应用特性:
1、枚举不可定义为abstract 或者 final,否则会引发编译器错误。
2、枚举实现了Comparable及Serializable接口,因此可以进行比较及序列化等操作,类型定义如下:
3、枚举类型只能通过内部的枚举常量进行初始化
4、枚举类型clone方法定义为final,即不可复制,否则会抛出异常:
5、枚举类型无法通过反射机制进行初始化。
6、枚举类型需要自定义处理序列化,反序列化,默认的序列化使用会抛出异常。
7、枚举类型equals定义为final,不可自定义覆盖,同关联hashCode方法。
8、枚举类型finalize定义为final,意味着枚举实例可能永远不会被垃圾回收。
二、枚举的初始化
如下图,我们定义EnvEnum类型枚举,然后通过PROD、RELEASE、DEV枚举常量初始化了三个EnvEnum实例:
枚举常量体可以包含参数,参数会通过构造函数进行枚举类型的初始化。
枚举体相当于定义了一个内部匿名类,但是不可包含构造函数及abstract方法。
枚举类型的构造函数有以下特殊约定限制:
1、构造函数默认为private修饰(不可外部初始化构造),不可使用public 或者 protected修饰,否则会导致编译错误。
2、不可在构造函数内调用父类构造函数。
3、枚举类型会默认声明无参构造函数。
三、枚举的一些特性
1、valueOf:根据枚举常量名称查找枚举实例。
枚举类型提供根据名称查询实例方法,需要注意的是,如果查找不到匹配的实例,则会抛出异常。
2、compareTo:提供枚举实例对比方法
对比需要再同类型枚举实例间,根据枚举实例的ordinal对比实现。
四、关于使用枚举、常量
其实,很多情况下,枚举和常量可以替代使用,对于第二部分 EnvEnum 示例,我们可以定义常量类如下:
但是,在实际应用中,在不同情景下的使用便捷性及代码复杂度上,却有着不小的区别:
1、对比、查找
当需要做同类型对比,查找类操作时,常量类需要对相应的常量组定义,实现相应的功能方法。
可预知的是在实际应用中,会有很多不同类型组常量应用需求,那么各组变量的对比,查找则需要分别去实现,而枚举相应的功能囊括在枚举类型定义中,可以直接使用。
2、关联性的使用
本篇中,我们定义了不同环境的(appId、appPort)配置使用,即,在使用PROD环境配置的appId时,同时可能会使用其appPort。在不同应用情景中,可能存在更多特性配置的关联使用,这就很可能造成使用中的关联性、匹配性的麻烦和混乱。比如,不小心组合使用了PROD_APP_ID和RELEASE_APP_PORT两个变量。
枚举实例将所有的关联特性包装在一起,更适合此种情景应用,如:(EnvEnum.PROD.getAppId()、EnvEnum.PROD.getAppPort())
总的来说,常量更适用于单一或者单一组合的全局性应用,而枚举更适合多组合多属性关联的复杂情景应用。
当然,我们这里只是说适合,不是必需。