TIP30 用enum代替int常量
也许我们常常会写以下类似的代码:
public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_GRANNY_SMITH = 2;
这种方法称为int枚举模式,它们在类型安全和使用方便性方面都有缺陷。
或者,这样的代码:
public static final String ORANGE_SIHUI = "SIHUIJU";
同样是不被推荐使用的。
从java 1.5版开始,推荐使用enum代替这些垃圾代码:
public enum Apple{FUJI,PIPPIN,GRANNY_SMITH}
public enum ORANGE{NAVEL,TEMPLE,BLOOD}
枚举类的本质: 通过公有的静态 final域为每个枚举常量导出实例的类。
特点:没有构造器,所以客户端既不能创建枚举类的实例,也不能对枚举类扩展。换句话说,它们是实例受控的。
枚举类型具有类的一些特性,比如定义构造方法,定义域和方法。
还可以在枚举类声明abstract方法,然后在声明枚举常量时实现这个方法。
比如下面是一个实现加减乘除运算的枚举类:
public enum Operation{
PLUS{
@Override
double apply(double x,double y){
return x+y;
}
},
MINUS{
@Override
double apply(double x, double y) {
return x-y;
}
},
TIMES{
@Override
double apply(double x, double y) {
return x*y;
}
},
DIVIDES{
@Override
double apply(double x, double y) {
return x / y;
}
};
abstract double apply(double x,double y);
}
再提醒一下,覆盖toString()会非常有用,在上述例子中,可以方便的打印算术式。
另外,枚举类型自带toValue()方法,它将常量的名字转变为常量本身。
总之,每当你需要一组固定常量的时候,就应当使用枚举,包括天然的枚举类型,比如行星,一周的天数、棋子的数目等等,或者菜单的选项、操作代码、命令行标记等等。如果多个枚举常量同时共享相同的行为,则考虑策略枚举。
TIP31 用实例域代替序数
有些枚举天生就与一个单独的int值相关联:
public enum Ensemble{
/**
* solo,二重奏,三重奏,四重奏.....
*/
SOLO,DUET,TRIO,QUARTET,QUINTET,SEXET,SEPET,OCTET,NONET,DECTET;
public int numberOfMusicians(){
return ordinal()+1;
}
}
numberOfMusicians方法返回每个枚举常量在类型中的数字位置,而且同时表示该类型由几位音乐家演奏。
比如,SOLO调用该方法返回1,表示该类型是由1位音乐家演奏。
虽然它可以正常工作,但是常量如果进行重新排序,numberOfMusicians方法将返回错误的数字,要想维护这个方法将会非常复杂。
正确的方法是将该int值保存在实例域中:
public enum Ensemble{
/**
* solo,二重奏,三重奏,四重奏.....
*/
SOLO(1),DUET(2),TRIO(3),QUARTET(4),
QUINTET(5),SEXET(6),SEPET(7),OCTET(8),
NONET(9),DECTET(10);
Ensemble(int size){
this.numberOfMusicians = size;
}
private final int numberOfMusicians;
public int numberOfMusicians(){
return numberOfMusicians;
}
}
基本上你用不上ordinary()这个方法,它是设计成用于像EnumSet和EnumMap这种基于枚举的通用数据结构的。