第三十条:用enum代替int常量
相比于声明成final static int 或string,使用枚举是更好的选择:
- int的缺点:无法打印出有效值,无法保证一个变量的int值一定有效(在你列出的备选值中)
- string:基于字符串比较带来性能问题;无法在编译时杜绝拼写错误等问题。
- enum的好处。
- 是单例的泛型。
- 保证被传到的参数一定是有效值。
- 包含同名常量的枚举类型可以在一个系统中共存
枚举可以声明方法和域,用这些方法可以将枚举从一个简单的集合变成一个全功能的抽象,比如这个行星的例子:
|
|
通过设定mass,radius和常量G,枚举可以调用方法返回自己的各种信息。这里所有域都应该是final的,而且尽量是私有的。
枚举中有个使用的函数values(),对一个枚举调用values()可以按照声明顺序返回他的值的数组,比如下面这个函数会答应Planet所有的值的名称:
|
|
枚举的toString如果你不重载他,默认会返回这个枚举值的名字,比如MERCURY。
枚举还有两个需要注意的方法
oridinal()
,他返回该枚举值在枚举中的位置,比如Planet.MERCURY.oridinal(),返回0。valueOf(String)
,他将常量的名字变为枚举值。比如Planet.valueOf("MERCURY")
返回Planet.MERCURY对象
枚举可以定义抽象方法,定义后每个枚举值都需要实现该方法,这有助于帮助你实现不同常量的特定逻辑而不至于被遗忘,比如:
|
|
第三十一条:用实例域代替序数 && 第三十三条 用EnumMap代替序数索引
虽然有oridinal()函数,但是并不建议使用它,因为他严重限制了程序的扩展性,新加一个枚举值在这种情况下非常危险。如果有相关需求最好在enum里面加一个域在存放相关值。
同样的,当你需要索引Enum时,建议使用EnumMap而不是序数
第三十二条:用EnumSet代替位域
有时候为了方便的求交集,程序员会写A=1<<0
,B=1<<1
这种,在判断时直接按位或。这种需求可以将常量AB声明成Enum,然后用EnumSet实现。
第三十四条:用接口模拟可伸缩的枚举类
因为枚举不能继承,所以无法有子枚举类和超枚举类,所以有这种扩展的需求可以让enum 实现接口,然后调用接口来模拟这种情况。
第三十五条: 注解优先于命名模式
命名模式是那种比如限定你的函数以test开头,然后会自动执行test开头的所有函数的方法,这个方法有一个问题就是假如你的test拼成了tset,在编译和运行时都不会报错,只是你这段程序永远也不会执行,从而导致错误的结果。
注解可以很好的解决这个问题。注解的使用可以参考文档1,文档2是对其中关键字@Inherited的说明
第三十六条:坚持使用Override注解
override可有有效避免覆盖父类函数时错误的写成了重载的问题,有助于编译器帮你发现bug。
本文采用创作共用保留署名-非商业-禁止演绎4.0国际许可证,欢迎转载,但转载请注明来自http://thousandhu.github.io,并保持转载后文章内容的完整。本人保留所有版权相关权利。
本文链接:http://thousandhu.github.io/2016/10/18/第六章-枚举和注解-effective-java/