注:阅读了effective java 讲诉enum的部分,做下笔记,下文中大部分代码来自effective java书中
枚举类型是指由一组固定的常量组成的合法值得类型。
使用枚举的好处:a,因为没有可以访问的构造器,枚举类型是真正的final;
b,枚举类型提供类编译时的类型安全。如:函数中声明一个参数类型为枚举类型的Apple时,那么调用方法时传递到参数上的任何非null对象一定是Apple的值之一, 而是用静态常量就无法保证;
c,包含同名常量的多个枚举类型可以和平共处,每个类型都有自己的命名空间
d,枚举类型允许添加任意的方法和域,并可实现接口。
1,常见的一组简单的枚举
如:
public enumApple {
FUJI,PIPPIN,CRANNY_SMITH
}
2,带有具体值的枚举(可自定义方法)
public enumApple {
FUJI(1), PIPPIN(2), CRANNY_SMITH(3);private final intcode;
Apple(intcode) {this.code =code;
}public intgetCode() {returncode;
}public static Apple fromCode(intcode) {for(Apple apple : Apple.values()) {if (apple.getCode() ==code)returnapple;
}return null;
}
}
3,多个参数,并带有运算方法
public enumPlanet {
MERCURY(3.303e+23, 2.4397e6),
VENUS(4.869e+24, 6.0518e6),
EARTH(5.976e+24, 6.37814e6),
MARS(6.421e+23, 3.3972e6),
JUPITER(1.9e+27, 7.1492e7),
SATURN(5.688e+26, 6.0268e7),
URANUS(8.686e+25, 2.5559e7),
NEPTUNE(1.024e+26, 2.4746e7),
PLUTO(1.27e+22, 1.137e6);private final doublemass;private final doubleradius;private final double surfaceGravity;//m/ s^2
public static final double G = 6.67300E-11;
Planet(double mass, doubleradius) {this.mass =mass;this.radius =radius;
surfaceGravity= G * mass / (radius *radius);
}public doublemass() {returnmass;
}public doubleradius() {returnradius;
}public double surfaceWeight(doubleotherMass) {return otherMass *surfaceGravity;
}
}
4,根据不同的常量有不同的方法
switch方法 ----不推荐(有可能新添加了常量却没有在switch中加入就悲剧了)
public enumOperation {
PLUS("+"),
MINUS("-"),
TIMES("*"),
DIVIDE("/");private finalString symbol;
Operation(String symbol){this.symbol=symbol;
}publicString getSymbol() {returnsymbol;
}double apply(double x,doubley){switch(this){case PLUS:return x +y;case MINUS:return x -y;case TIMES:return x *y;case DIVIDE:return x /y;
}throw new AssertionError("unknown operation: "+this);
}
推荐:constant-specific method implementation
public enumOperation {
PLUS("+") {public double apply(double x, doubley) {return x +y;
}
},
MINUS("-") {public double apply(double x, doubley) {return x -y;
}
},
TIMES("*") {public double apply(double x, doubley) {return x *y;
}
},
DIVIDE("/") {public double apply(double x, doubley) {return x /y;
}
};private finalString symbol;
Operation(String symbol) {this.symbol =symbol;
}publicString getSymbol() {returnsymbol;
}public abstract double apply(double x, doubley);
}
5,策略枚举 strategy enum
先来看一种情况:通过一周的工作时间来计算工资,工作时间8小时,额外算加班,周末工作也算加班
首先我们可以使用switch来做,这样看起来十分简单
public enumPayrollDay {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FIRDAY, SATURDAY, SUNDAY;private static final int HOURS_PER_SHIFT = 8;double pay(double hoursWorked, doublepayRate) {double basePay = hoursWorked *payRate;doubleovertimePay;switch (this) {caseSATURDAY:caseSUNDAY:
overtimePay= hoursWorked * payRate * 2;default:
overtimePay= hoursWorked <= HOURS_PER_SHIFT ? 0: (hoursWorked- HOURS_PER_SHIFT) * payRate * 2;break;
}return basePay +overtimePay;
}
}
但是同样有可能出现上面提到不严谨的问题,当枚举常量增加时,switch可能忘记加入
使用策略枚举时 如下:
public enumPayrollDay {
MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), WEDNESDAY(
PayType.WEEKDAY), THURSDAY(PayType.WEEKDAY), FIRDAY(PayType.WEEKDAY), SATURDAY(
PayType.WEEKEND), SUNDAY(PayType.WEEKEND);private finalPayType payType;
PayrollDay(PayType payType) {this.payType =payType;
}publicPayType getPayType() {returnpayType;
}double pay(double hoursWorked, doublepayRate) {returnpayType.pay(hoursWorked, payRate);
}enumPayType {
WEEKDAY {
@Overridedouble overtimePay(double hours, doublepayRate) {return hours < HOURS_PER_SHIFT ? 0 : (hours -HOURS_PER_SHIFT)* payRate * 2;
}
},
WEEKEND {
@Overridedouble overtimePay(double hours, doublepayRate) {return hours * payRate * 2;
}
};private static final int HOURS_PER_SHIFT = 8;abstract double overtimePay(double hours, doublepayRate);double pay(double hoursWorked, doublepayRate) {double basePay = hoursWorked *payRate;return basePay +overtimePay(hoursWorked, payRate);
}
}
}
6,上面几个例子中都不推荐时间switch,那么什么时候使用呢
枚举中的switch语句适用于给外部的枚举类型增加特定于常量的行为。如:上面例子中的operation 如果希望他有一个方法返回对应的逆运算
public staticOperation inverse(Operation op) {switch(op) {casePLUS:returnOperation.MINUS;caseMINUS:returnOperation.PLUS;caseTIMES:returnOperation.DIVIDE;caseDIVIDE:returnOperation.TIMES;default:throw new AssertionError("unknown operation : " +op);
}
}