第34条 用enum代替int常量java两种特殊的引用类型
- 类 :枚举类型
- 接口 :注解类型
枚举类型:由一组固定的常量组成合法值的类型
java的枚举类型是功能齐全的类,本质还是int值, 通过公有的静态final域为每个枚举常量导出一个实例。枚举类型没有可以访问的构造器,是真正的final类,是实例受控的。
枚举类型允许添加任意的方法和域,并实现任意的接口(提供了所有的Object方法的高级实现,实现了Comparable、Serializable接口…)
为了将数据与枚举常量联系起来,需要声明实例域(均为final),并编写构造器
public enum Demo {
A(1, 2),
B(3, 4),
C(1, 1);
private final int i1;
private final int i2;
Demo(int i1, int i2){
this.i1 = i1;
this.i2 = i2;
}
public int sum(){
return i1 + i2;
}
}
Enum类的常用方法
| 方法 | 描述 |
|---|---|
| values() | 以数组的形式返回枚举类型的所有成员 |
| valueOf() | 将普通字符串转换为枚举实例 |
| compareTo() | 比较两个枚举成员在定义时的顺序 |
| ordinal() | 获取枚举成员的索引位置 |
| toString() | 返回每个枚举值的声明名称 |
如果一个枚举具有普遍适应性,则应该成为顶层类, eg: java.math.RoundingMode(十进制小数舍入模式)
特定与常量的方法实现
public enum Operation{
PLUS("+") {
public double apply(double x, double y){return x + y;}
},
MINUS("-") {
public double apply(double x, double y){return x - y;}
},
TIMES("*") {
public double apply(double x, double y){return x * y;}
},
DIVIDE("/") {
public double apply(double x, double y){return x / y;}
};
private final String symbol;
Operation(String symbol){
this.symbol = symbol;
}
public abstract double apply(double x, double y); // 必须是抽象的,每个枚举实例都要实现
}
策略枚举
public enum PayrollDay{
MONAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
SATURDAY(PayType.WEEKEND), SUNDAY(Paytype.WEEKEND);
private final PayType payType;
payrollDay(PayType payType) {
this.payType = payType;
}
PayrollDay(){this(PayType.WEEKDAY)}
private enum PayType{ // 私有的嵌套枚举类
WEEKDAY{
int overtimePay(int mins, int payRate){
return ...
}
},
WEEKEND{
int overtimePay(int mins, int payRate){
return ...
}
};
abstract int overtimePay(int mins, int payRate);
private static final int MINS_PER_SHIFT = 8 * 60;
int pay(int mins, int payRate){
int basePay = mins * payRate;
return basePay + overtimePay(mins, payRate);
}
}
}
- 每当需要一组固定的常量,并且在编译时就知道其成员的时候,就应该使用枚举
- 每个枚举常量都需要不同的行为,考虑特定于常量的方法
- 多个但非所有枚举常量同时共享相同的行为需要考虑策略枚举
第35条 用实例域代替序数
永远不要根据实例的序数导出与它关联的值
// 错误示例 // 问题在于如果修改枚举常量增加或减少,则ordinal()会变,可能造成错误使用
public enum NoDoThis{
A, B, C;
public int getOrder() { return ordinal() + 1;}
}
// 正确示例
public enum DoThis{
A(1), B(11), C(333);
private final int order;
DoThis(int order) { this.order = order};
public int getOrder() {return order;}
}
一般不使用ordinal(), 它是设计用于像 EnumSet 和 EnumMap 这种基于枚举的通用数据结构
第36条 用EnumSet代替位域
用 OR 位运算符将几个常量合并到一个集合中,称作位域
// 位域
public class Text{
public static final int STYLE_BOLD = 1 << 0;
public static final int STYLE_ITALIC = 1 << 1;
...
public void applyStyles(int styles){...}
}
text.applyStyles(STYLE_BOLD | STYLE_ITALIC);
// EnumSet
public class Text{
public enum Style{
BOLD, ITALIC, UNDERLINE, STRIKETHROUGH
}
public void applyStyles(Set

