Effective Java 学习笔记之枚举
来源:互联网 发布:php高级视频教程下载 编辑:程序博客网 时间:2024/06/05 00:12
1.用enum代替int常量
1)为了将数据和枚举常量关联起来 得声明实例域,并编写一个带有数据并将数据保存在域中的构造器。
2)枚举天生就是不可变的,因此所有的域都应该是final的。它们可以是公有的,但是最好做成私有并提供公有的访问方式
3)枚举类型还允许添加任意的方法和域 并实现任意的接口
4)提供了所有Object方法的高级实现 实现了Comparable和Serializable接口,并设计了序列化方式
public enum Planet { MERCURY(3.302E+23, 2.439E6), VENUS(4.869e+24, 6.052e6), EARTH(5.975e+24, 6.378e6), MARS(6.419e+23, 3.393e6), JUPITER(1.899e+27, 7.149e7), SATURN(5.685e+26, 6.027e7), URANUS(8.683e+25, 2.556e7), NEPTUNE(1.024e+26, 2.477e7); private final double mass; private final double radius; private final double surfaceGravity; private static final double G = 6.67300E-11; Planet(double mass, double radius) { this.mass = mass; this.radius = radius; surfaceGravity = G * mass / (radius * radius); } public double getMass() { return mass; } public double getRadius() { return radius; } public double getSurfaceGravity() { return surfaceGravity; } public double getSurfaceWeight(double mass) { return mass * surfaceGravity; }}
扩展:需要为每个常量添加不同的行为
public enum Operation1 { PLUS, MINUS, TIMES, DIVIDE; double apply(double x, double y) { 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 op:" + this); }}
上面的代码存在一些问题,当为枚举类添加新的常量后,忘记为其提供相应apply的实现,编译不会出现错误提示,然而运行结果却不是希望的
因此可以进行修改
提供一个抽象的apply方法,这样每个常量都必须实现这个抽象方法,否则编译就会报错
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; } }, DIVIDE { @Override double apply(double x, double y) { return x / y; } }; abstract double apply(double x, double y);
有时候复写toString方法也会非常有用
public enum Operation2 { 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; } }, DIVIDE("/") { @Override double apply(double x, double y) { return x / y; } }; abstract double apply(double x, double y); private String symbol; Operation2(String symbol) { this.symbol = symbol; } @Override public String toString() { return symbol; }}
public class OpeartionTest { public static void main(String[] args) { double d1 = 1.3; double d2 = 2.6; for (Operation2 o:Operation2.values()){ System.out.printf("%f %s %f = %f%n",d1,o,d2,o.apply(d1,d2)); } }}
输出结果
1.300000 + 2.600000 = 3.9000001.300000 - 2.600000 = -1.3000001.300000 * 2.600000 = 3.3800001.300000 / 2.600000 = 0.500000
5)枚举类型有一个自动产生的valueOf(String)方法,它将常量的名字转变成常量本身。
Operation2 plus = Operation2.valueOf("PLUS");System.out.println(plus);
输出结果
+
如果在枚举类型中覆盖toString,要考虑编写一个fromString方法,将定制的字符串表示法变回相应的枚举,考虑用map保存
private static Map<String,Operation3> operation3Map = new HashMap<>();static { for (Operation3 o:Operation3.values()){ operation3Map.put(o.toString(),o); }}public static Operation3 fromString(String str){ return operation3Map.get(str);}
测试方法
Operation3 minus = Operation3.fromString("-");System.out.println(minus);
输出结果
-
6)特定于常量的方法有一点不足,它们是的在枚举常量中共享代码变得困难
public enum PayrollDay { MONDAY, TUESDAT, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; /** * 正常工作时间 */ private static final int HOURS_PER_SHIFT = 8; /** * 计算工资 * * @param hoursWorked 工作时间 * @param payRate 薪资 * @return 工资 */ double pay(double hoursWorked, double payRate) { double basePay = hoursWorked * payRate; double overtimePay; switch (this) { case SATURDAY: case SUNDAY: overtimePay = hoursWorked * payRate / 2; default: overtimePay = hoursWorked <= HOURS_PER_SHIFT ? 0 : (hoursWorked - HOURS_PER_SHIFT) * payRate / 2; } return basePay + overtimePay; }}
当添加一个元素而没有添加相应的case时就会出现问题
可以使用枚举策略来解决,即讲加班工资的计算转移到一个私有的嵌套枚举中,将这个枚举的实例传到外部枚举的构造器中,这样外部枚举就可以将工资计算委托给内部枚举不需要再用switch进行转化了
public enum PayrollDay2 { MONDAY(PayType.PAY_WEEKDAY), TUESDAY(PayType.PAY_WEEKDAY), WEDNESDAY(PayType.PAY_WEEKDAY), THURSDAY(PayType.PAY_WEEKDAY), FRIDAY(PayType.PAY_WEEKDAY), SATURDAY(PayType.PAY_WEEKEND), SUNDAY(PayType.PAY_WEEKEND); private final PayType payType; PayrollDay2(PayType payType) { this.payType = payType; } public double pay(double hoursWork, double payRate) { return this.payType.pay(hoursWork, payRate); } private enum PayType { PAY_WEEKDAY { @Override double overtimePay(double hoursWork, double payRate) { return hoursWork <= HOUR_SHIFT_TIME ? 0 : (hoursWork - HOUR_SHIFT_TIME) * payRate / 2; } }, PAY_WEEKEND { @Override double overtimePay(double hoursWork, double payRate) { return hoursWork * payRate; } }; private static final int HOUR_SHIFT_TIME = 8; abstract double overtimePay(double hoursWork, double payRate); public double pay(double hoursWork, double payRate) { double basePay = hoursWork * payRate; double overtimePay = overtimePay(hoursWork, payRate); return basePay + overtimePay; } }}
2.用实例域代替序数
public enum Ensemble { SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUEINTET(5), SEXTET(6), SEPTET(7); private final int numberOfMusicians; Ensemble(int size) { this.numberOfMusicians = size; } public int getNumberOfMusicians() { return numberOfMusicians; } //public int numberOfMusicians() { // //ordinal():返回每个枚举常量在类型中的数字位置 // return ordinal() + 1; //}}
3.用接口模拟可伸缩的枚举
public interface Operation { double apply(double x, double y);}public enum BaseOperation implements Operation { PLUS { @Override public double apply(double x, double y) { return x + y; } }, MINUS { @Override public double apply(double x, double y) { return x - y; } }, TIMES { @Override public double apply(double x, double y) { return x * y; } }, DIVIDE { @Override public double apply(double x, double y) { return x / y; } };}public enum ExtendOperation implements Operation { MOD { @Override public double apply(double x, double y) { return x % y; } }, EXP { @Override public double apply(double x, double y) { return Math.pow(x, y); } };}
测试方法
public class ExtendOperationTest { public static void main(String[] args) { double d1 = 1.3; double d2 = 2.6; test(ExtendOperation.class, d1, d2); test1(Arrays.asList(ExtendOperation.values()), d1, d2); } private static <T extends Enum<T> & Operation> void test(Class<T> opSet, double d1, double d2) { for (Operation o : opSet.getEnumConstants()) { System.out.printf("%f %s %f = %f%n", d1, o, d2, o.apply(d1, d2)); } } private static void test1(Collection<? extends Operation> opSet, double d1, double d2) { for (Operation o : opSet) { System.out.printf("%f %s %f = %f%n", d1, o, d2, o.apply(d1, d2)); } }}
输出结果
1.300000 MOD 2.600000 = 1.3000001.300000 EXP 2.600000 = 1.9781201.300000 MOD 2.600000 = 1.3000001.300000 EXP 2.600000 = 1.978120
阅读全文
0 0
- Effective Java 学习笔记之枚举
- Java学习笔记之枚举
- Effective Java 学习笔记之泛型
- Effective Java 学习笔记之异常
- effective java学习笔记
- Effective java学习笔记
- effective java学习笔记
- effective java 学习笔记
- Effective Java 学习笔记
- Effective Java 学习笔记
- Effective Java学习笔记
- Effective Java学习笔记
- Effective Java学习笔记
- Effective Java 学习笔记
- Effective java --学习笔记
- java学习笔记之 --------枚举(enum)
- Java学习笔记之枚举类
- Java之学习笔记(30)------------枚举
- numpy 中 newaxis函数的使用
- [Unity3D·CSV篇]目录
- python基础学习五:迭代和列表生成式
- CCF 学生排队
- 无名管道pipe使用方法
- Effective Java 学习笔记之枚举
- java基础【04】 继承和多态
- 【c语言】单链表的基础面试题
- 一、Mac下Appium环境搭建
- NumPy 音频和图像处理
- socket与http的区别
- Python中元组与列表的区别
- YOLOV2
- Python异常