使用 EnumSet 替代位属性

This commit is contained in:
尉勇强2
2020-04-15 20:16:11 +08:00
parent 3a137f7013
commit 242c7c8d58
10 changed files with 155 additions and 6 deletions

View File

@@ -55,4 +55,5 @@ Java 枚举类型背后的基本思想很简单:它们是通过公共静态 `f
那么你应该什么时候使用枚举呢? 任何时候使用枚举都需要一组常量,这些常量的成员在编译时已知。 当然,这包括“天然枚举类型”,如行星,星期几和棋子。 但是它也包含了其它你已经知道编译时所有可能值的集合,例如菜单上的选项,操作代码和命令行标志。 **一个枚举类型中的常量集不需要一直保持不变**。 枚举功能是专门设计用于允许二进制兼容的枚举类型的演变。
总之,枚举类型优于 `int` 常量的优点是令人信服的。 枚举更具可读性,更安全,更强大。 许多枚举不需要显式构造方法或成员,但其他人则可以通过将数据与每个常量关联并提供行为受此数据影响的方法而受益。 使用单一方法关联多个行为可以减少枚举。 在这种相对罕见的情况下,更喜欢使用常量特定的方法来枚举自己的值。 如果一些(但不是全部)枚举常量共享共同行为,请考虑策略枚举模式。
总之,枚举类型优于 `int` 常量的优点是令人信服的。 枚举更具可读性,更安全,更强大。 许多枚举不需要显式构造方法或成员,但其他人则可以通过将数据与每个常量关联并提供行为受此数据影响的方法而受益。 使用单一方法关联多个行为可以减少枚举。 在这种相对罕见的情况下,更喜欢使用常量特定的方法来枚举自己的值。 如果一些(但不是全部)枚举常量共享共同行为,请考虑策略枚举模式。

View File

@@ -0,0 +1,14 @@
## 使用实例属性替代序数
所有枚举都有一个 `ordinal` 方法,它返回每个枚举常量类型的数值位置。
- [Item35Example01.java](EnumsAnnotations/src/main/java/com/jueee/item35/Item35Example01.java):虽然这个枚举能正常工作,但对于维护来说则是一场噩梦。
如果常量被重新排序,`numberOfMusicians` 方法将会中断。
- [Item35Example02.java](EnumsAnnotations/src/main/java/com/jueee/item35/Item35Example02.java):不要从枚举的序号中得出与它相关的值,将其保存在实例属性中。
枚举规范对此 `ordinal` 方法说道:“大多数程序员对这种方法没有用处。 它被设计用于基于枚举的通用数据结构,如 `EnumSet``EnumMap`。“
除非你在编写这样数据结构的代码,否则最好避免使用 `ordinal` 方法。

View File

@@ -1,5 +1,9 @@
package com.jueee.item34;
/**
*
* @author hzweiyongqiang
*/
public class Item34Example04 {
// Enum type that switches on its own value - questionable

View File

@@ -4,12 +4,32 @@ public class Item34Example05 {
// Enum type with constant-specific method implementations
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;}};
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 abstract double apply(double x, double y);
public abstract double apply(double x, double y);
}
public static void main(String[] args) {

View File

@@ -5,21 +5,25 @@ public class Item34Example06 {
// Enum type with constant-specific class bodies and data
public enum 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;
}

View File

@@ -23,11 +23,13 @@ public class Item34Example09 {
// The strategy enum type
private enum PayType {
WEEKDAY {
@Override
int overtimePay(int minsWorked, int payRate) {
return minsWorked <= MINS_PER_SHIFT ? 0 : (minsWorked - MINS_PER_SHIFT) * payRate / 2;
}
},
WEEKEND {
@Override
int overtimePay(int minsWorked, int payRate) {
return minsWorked * payRate / 2;
}

View File

@@ -0,0 +1,20 @@
package com.jueee.item35;
/**
*
* @author hzweiyongqiang
*/
public class Item35Example01 {
/**
* Abuse of ordinal to derive an associated value - DON'T DO THIS
* @author hzweiyongqiang
*/
public enum Ensemble {
SOLO, DUET, TRIO, QUARTET, QUINTET,
SEXTET, SEPTET, OCTET, NONET, DECTET;
public int numberOfMusicians() { return ordinal() + 1; }
}
}

View File

@@ -0,0 +1,24 @@
package com.jueee.item35;
/**
*
* @author hzweiyongqiang
*/
public class Item35Example02 {
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5), SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8), NONET(9),
DECTET(10), TRIPLE_QUARTET(12);
private final int numberOfMusicians;
Ensemble(int size) {
this.numberOfMusicians = size;
}
public int numberOfMusicians() {
return numberOfMusicians;
}
}
}

View File

@@ -0,0 +1,28 @@
package com.jueee.item36;
/**
*
* @author hzweiyongqiang
*/
public class Item36Example01 {
// Bit field enumeration constants - OBSOLETE!
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
public static final int STYLE_UNDERLINE = 1 << 2; // 4
public static final int STYLE_STRIKETHROUGH = 1 << 3; // 8
// Parameter is bitwise OR of zero or more STYLE_ constants
public void applyStyles(int styles) {
System.out.println(styles);
}
}
public static void main(String[] args) {
Item36Example01 example = new Item36Example01();
Text text = example.new Text();
text.applyStyles(Text.STYLE_BOLD | Text.STYLE_ITALIC); // 3
}
}

View File

@@ -0,0 +1,32 @@
package com.jueee.item36;
import java.util.EnumSet;
import java.util.Set;
/**
*
* @author hzweiyongqiang
*/
public class Item36Example02 {
public enum Style {
BOLD, ITALIC, UNDERLINE, STRIKETHROUGH
}
// EnumSet - a modern replacement for bit fields
public class Text {
// Any Set could be passed in, but EnumSet is clearly best
public void applyStyles(Set<Style> styles) {
System.out.println(styles);
}
}
public static void main(String[] args) {
Item36Example02 example = new Item36Example02();
Text text = example.new Text();
// EnumSet 类提供了一组丰富的静态工厂,可以轻松创建集合
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC)); // 3
}
}