枚举
这个主要是effective java的笔记,大部分配的是工作中用的例子,部分还是书上的例子
-
用enum代替int常量,
a.因为没有可以访问的构造器,枚举类型是真正的final
b.枚举天生就是不可变的,因此所有的域都应该是final的,他们可以是公有的,但最好将他们做成私有的,并提供公有的访问方法.
c.特定于常量的方法实现,枚举里加接口, 各常量里来实现 ,而不是if-else,switch
d.策略枚举,public enum QmqType { CREATE_ORDER(".order", "生单", 99, 99) { @Override public int getGdp(String site) { return ConfigServiceUtil.getGdpAndError(site, QmqType.CREATE_ORDER, ConfigType.GDP); } @Override public int getMaxError(String site) { return ConfigServiceUtil.getGdpAndError(site, QmqType.CREATE_ORDER, ConfigType.ERROR); } }, PURCHASE(".purchase", "采购", 99, 99) { @Override public int getGdp(String site) { return ConfigServiceUtil.getGdpAndError(site, QmqType.PURCHASE, ConfigType.GDP); } @Override public int getMaxError(String site) { return ConfigServiceUtil.getGdpAndError(site, QmqType.PURCHASE, ConfigType.ERROR); } }, TICKET(".ticket", "出票", 99, 99) { @Override public int getGdp(String site) { return ConfigServiceUtil.getGdpAndError(site, QmqType.TICKET, ConfigType.GDP); } @Override public int getMaxError(String site) { return ConfigServiceUtil.getGdpAndError(site, QmqType.TICKET, ConfigType.ERROR); } }; // redis中存的类型后缀 public String VALUE; // 发短信中的类型说明 public String NAME; // config中没有配置或者配置出错,提供的default监控值 public final int DEFAULT_GDP; // 同上,default允许的失败值 public final int DEFAULT_ERROR; public abstract int getGdp(String site); public abstract int getMaxError(String site); QmqType(String value, String name, Integer defaultGdp, Integer defaultError) { this.VALUE = value; this.NAME = name; this.DEFAULT_GDP = defaultGdp; this.DEFAULT_ERROR = defaultError; } }
-
用实例域代替序数(用的较多了,一般都直接不使用序数)
public enum CabinTypeEnum { FIRST_CLASS_CABIN(1), BUSINESS_CLASS_CABIN(2), ECONOMY_CLASS_CABIN(0); private final int code; CabinTypeEnum(int code) { this.code = code; } public int getCode() { return code; } }
-
用EnumSet代替位域,之前看到scheduler的设计很牛逼,这才发现还有更好的方式。
// 不好 public class Text { public static final int STYLE_BOLD = 1 << 0; public static final int STYLE_BOLD = 1 << 1; public static final int STYLE_BOLD = 1 << 2; public static final int STYLE_BOLD = 1 << 3; public void applyStyles(int xx) { ... } } text.applyStyles(STYLE_BOLD | STYLE_ITALIC); // 好 public class Text { public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH } public void applyStyles(Set< Style > styles) { .. } } text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC) );
-
用EnumMap来代替序数索引
a.使用EnumMap来关联enum的数据 (eg: 多舱等,每个舱等对应多个舱位)
public enum CabinTypeEnum { FIRST_CLASS_CABIN(1), BUSINESS_CLASS_CABIN(2), ECONOMY_CLASS_CABIN(0); private final int code; CabinTypeEnum(int code) { this.code = code; } public int getCode() { return code; } } // 不好 Map<int,List<Cabin>> map = Maps.newHashMap(); for(CabinTypeEnum cabinTypeEnum : enumMap.keySet()){ map.put(cabinTypeEnum.getCode(),Lists.<Cabin>newArrayList()); } map.get(CabinTypeEnum.FIRST_CLASS_CABIN); // 好 Map<CabinTypeEnum,List<Cabin>> enumMap = Maps.newEnumMap(CabinTypeEnum.class); for (CabinTypeEnum cabinTypeEnum : enumMap.keySet()) { enumMap.put(cabinTypeEnum, Lists.<Cabin>newArrayList()); } enumMap.get(CabinTypeEnum.FIRST_CLASS_CABIN);
b.使用嵌套的EnumMap来关联enum pairs, (eg :水,气,冰 升华,熔化,凝华,液化..)
-
用接口模拟可伸缩的枚举
eg: 一个操作的enum,里边实现了加减乘除,但是你又想加入一些额外的操作,取余,幂等操作,又想有所区别表示基本操作和额外操作,使用接口就太棒了
public interface Operation {
double apply(double x, double y);
}
public enum BasicOperation implements 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;
BasicOperation(String symbol) { this.symbol = symbol; }
@Override
public String toString() {
return symbol;
}
}
// Extend from BasicOperation
public enum ExtendedOperation implements Operation {
EXP("^") { public double apply(double x, double y) { return Math.pow(x, y); } },
REMAINDER("%") { public double apply(double x, double y) { return x % y; } };
private final String symbol;
ExtendedOperation(String symbol) { this.symbol = symbol; }
@Override
public String toString() {
return symbol;
}
}
public static void main(String[] args ){
double x = 1.1;
double y = 2.2;
test(ExtendedOperation.class, x, y);
}
// 这个还没见过哎 &
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) );
}
参考
Effective java
[1]http://allenlsy.com/NOTES-of-Effective-Java-5/