第34条:用Enum代替int常量

枚举类型(enum type) 是指一组固定的常量组成合法值的类型,例如一年中的季节、太阳系中的行星或者一副牌中的花色

而在枚举产生之前,或者一些程序员的开发习惯,为了做一个区分度,通常会选择使用 int 类型的常量,如下:

  1. public static final int DAY_MONDAY = 1;
  2. public static final int DAY_TUESDAY = 2;
  3. public static final int DAY_WEDNESDAY = 3;
  4. ......
  5. public static final int ORANGE_NAVEL = 0;
  6. public static final int ORANGE_TEMPLE = 1;
  7. public static final int ORANGE_BLOOD = 2;

但是看这个标题也明白了,int 常量枚举的这种方式,会有很多的弊端:

  1. DAY_XXX 与 ORANGE_XXX 比较的时候,编译器和执行时都不会出现错误。
  2. 把 DAY_XXX 传入 需要一个 ORANGE_XXX 的方法中,编译器和执行时都不会出现错误。
  3. int 枚举是编译时异常,这个具体的 int 值会被编译到使用它们的客户端中,所以与这个 int 枚举类型关联的值发生了改变,必须重新编译,否则虽然程序还可以运行,但实际上,这个结果已经不太准确了。
  4. 想要打印一个 int 枚举很麻烦,而且就算打印出了,也只是显示一个数字,没有什么意义。

而 Java 后来创建了一个枚举类型的概念,格式如下:

  1. public enum DAY {
  2. DAY_MONDAY,
  3. DAY_TUESDAY,
  4. ......
  5. }
  6. public enum ORANGE {
  7. ORANGE_NAVEL,
  8. ORANGE_TEMPLE,
  9. ORANGE_BLOOD
  10. }

枚举类型就可以解决 int 常量枚举的问题

  1. 枚举类型定义了类的安全检查机制,例如当你的方法参数类型为枚举类型 DAY 的时候,那么它可以保证这个参数一定是这个 DAY 枚举类中的任何一个有效值(除了 null)。
  2. 同时通过 == 比较相等,或者赋值语句赋值的时候,都会去判断类型。
  3. 同时包含同名常量的多个枚举类型可以共存,因为每个类型有自己的命名空间,增加或重新排列枚举类型的常量,无需重新编译客户端的代码。
  4. 获取字符串直接 toString。
  5. 同时枚举类型的可读性也变强了,可以让开发人员对业务属性等有更好的熟悉和全貌的认识。
  6. 解决了硬编码问题。

第35条:用实例域代替序数(暂不常用,后期补充)

第36条:用EnumSet代替位域(暂不常用,后期补充)

第37条:用EnumMap代替序数索引(暂不常用,后期补充)

第38条:用接口模拟可扩展枚举(暂不常用,后期补充)

第39条:注解优先于命名模式

通过命名的方式来约定某种规范,其实往往不如通过注解的方式,注解的方式会更加清晰明确。

第40条:坚持使用@Override注解

这个注解表示,被注解的方法生命覆盖了超类型中的一个方法类型。而且@Override注解的生命周期是代码级,等生成字节码 class 文件的时候就没了。

第41条:用标记接口定义类型

例如 Serializable、Cloneable 等接口,进入源码后就会发现是一个空的接口,它仅仅作为一个标记,用来表明当前类或者接口符合某一种规范等,这就是标记接口的定义。

而标记注解,就是一种和标记接口很像的概念,注解中不包含任何成员,通过 isAnnotationPresent 方法来判断。

注:如果仅用于类或接口,可以优先考虑用接口标记的方式。如果需要作用于成员或方法,那只能使用注解标记。