0%

Effective Java 第三版 (5) 枚举和注解

枚举和注解

枚举和注解类型是 Java 1.5 增加的两个新的引用类型。

§ 用枚举类型代替整型常量

int 枚举在类型安全性和使用方便性方面没有任何帮助

1
2
public enum Apple {FUJI, PIPPIN, GRANNY_SMITH}
public enum Orange {NAVEL, TEMPLE, BLOOD}

§ 用实例属性代替序数

所有枚举都有一个 ordinal 方法,它返回每个枚举常量类型的数值位置,不应该依赖这个位置,因为位置可能会经常变化。

永远不要从枚举的序号中得出与它相关的值,而应该保存在属性实例中。

1
2
3
4
5
6
7
8
9
10
11
12
13
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5), SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8), NONET(9), DECTET(10), TRIPLE_QUARTET(12);

private final int numberOfMusicians;

Ensemble(int size) {
this.numberOfMusicians = size;
}

public int numberOfMusicians() {
return numberOfMusicians;
}
}

ordinal 的设计主要用于基于枚举的通用数据结构,如 EnumSetEnumMap,除非你编写这样的数据结构代码,否则避免使用 ordinal 方法。

§ 用 EnumSet 代替位属性

如果枚举类型元素主要用于集合中,传统做法是使用 int 枚举,将 2 的不同次幂赋值给每个常量。这样的表示方式允许你使用按位或运算:text.applyStyles(STYLE_BOLD | STYLE_ITALIC)

这种方法有很多弊端:无法遍历、需要提前预测最大位数等。

1
2
3
4
5
6
7
8
9
10
public class Text {
public enum Style {BOLD, ITALTIC, UNDERLINE, STRIKETHROUGH}

// 注意:这里参数使用的是 Set 接口,而不是 EnumSet 实现
public void appleStyles(Set<Style> styles) {
...
}
}

text.applyStyles(EnumSet.of(Style.Bold, Style.ITALIC));

§ 用 EnumMap 代替序数索引

§ 用接口模拟可扩展的枚举

§ 注解优先于命名模式

历史原因,Junit 测试框架要求它的用户一定要用 test*** 作为测试方法名称的开头。现在已经是直接使用 @Test

§ 坚持使用 @Override 注解

使用 @Override 可以帮你做编译检查。

它表明带此注解的方法声明重写了父类的声明。

§ 用标记接口定义类型

标记接口是没有包含方法声明的接口。而只是指明一个类实现了具有某种属性的接口。

Serializable 接口,通过实现这个接口,类表明它的实例可以被写到 ObjectOutputStream被序列化