第6章.枚举和注解
30.用enum代替int常量
总而言之,与int常量相比,枚举类型的优势是不言而喻的,枚举要易读的多,也更加安全,功能更加强大。许多枚举都不需要显式的构造器或者成员,但许多其他枚举则受益于“每个常量与属性的关联”以及”提供行为受这个属性影响的方法”。如果多个枚举常量同时共享相同的行为,则考虑策略枚举。与int常量相比,枚举有个小小的性能缺点,即装载和初始化枚举时会有空间和时间的成本。
31.用实例域代替序数
所有的枚举都有一个oridinal
方法,它返回每个枚举常量在类型中的数字位置。
永远不要根据枚举的序数导出与它关联的值,而是要将它保存在一个实例域中。
Enum规范中谈到oridinal
时这么写到:大多数程序员都不需要这个方法。它是设计成用于像EnumSet
和EnumMap
这种基于枚举的通用数据结构的。
32.用EnumSet代替位域
正是因为枚举类型要用在集合Set中,所以没有理由用位域来表示它。EnumSet类集位域的简洁和性能优势及枚举类型的所有优点于一身。
33.用EnumMap代替序数索引
最好不要用序数来索引数组,而要使用EnumMap
。若要表示的这种关系是多维的,就使用EnumMap<...,EnumMap<...>>
。
34.用接口模拟可伸缩的枚举
虽然枚举类型不是可扩展的,但接口类型则是可扩展的,它是用来表示API中的操作的接口类型。你可以定义另一个枚举类型,它实现这个接口,不够用这个新类型的实例代替基本类型。
public interface Operation {
double apply(double a, double b);
}
public enum BasicOperation implements Operation{
PLUS("+") {
public double apply(double a, double b) { return a + b;}
},
MINUS("-") {
@Override
public double apply(double a, double b) {
return a - b;
}
},
TIMES("*") {
@Override
public double apply(double a, double b) {
return a*b;
}
},
DIVIDE("/") {
@Override
public double apply(double a, double b) {
return a/b;
}
};
private final String symbol;
BasicOperation(String s) {
this.symbol = s;
}
@Override
public String toString() {
return symbol;
}
}
public class Test {
private static <T extends Enum<T> & Operation> void test(Class<T> opSet, double x, double y) {
for (Operation op : opSet.getEnumConstants()) {
System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
}
}
public static void main(String[] args) {
double a = 10.0;
double b = 5.0;
test(BasicOperation.class, a, b);
}
}
35.注解优先于命名模式
36.坚持使用@Override注解
37.用标记接口定义类型
标记接口有两点胜过标记注解。首先,也是最重要的一点是,标记接口定义的类型是由被标记类的实例实现的;标记注解则没有定义这样的类型。这个类型允许你在编译时不做在使用标记注解的情况下要到运行时才能捕捉到的错误。另一个优点是,他们可以被更加精确地进行锁定。如果注解类型利用@Target(ElementType.TYPE)
声明,它就可以被应用到任何类或者接口。假设有一个标记只适用于特殊接口的实现,如果将它定义为一个标记接口,就可以用它将唯一的接口扩展成它适用的接口。
标记注解胜过标记接口的最大优点在于,它可以通过默认的方式添加一个或者多个注解类型元素,给已被使用的注解类型添加更多的信息。
什么时候用标记注解,什么时候用标记接口呢?很显然,如果标记是应用到任何程序元素而不是类和接口,就必须使用注解,因为只有类和接口可以用来实现或者扩展接口。
总而言之,标记接口和标记注解都各有好处。如果想要定义一个任何新方法都不会与之关联的类型,标记接口就是最好的选择。如果想要标记程序元素而非类和接口,考虑到未来可能要给标记添加更多的信息,或者标记要适合于已经广泛使用了注解类型的框架,那么标记注解就是正确的选择。