前言
enum 的一些小小编码建议,以及扩展知识(开发中可能会用到)
存在问题的Enum示例
public enum Operation {
PLUS("+","加法"),
MINUS("-","减法"),
TIMES("*","乘法"),
DIVIDE("/","除法"),
NULL("",""),
;
//符号
private String symbol;
private String display;
Operation(String symbol, String display) {
this.symbol = symbol;
this.display = display;
}
public String getSymbol() {
return symbol;
}
public String getDisplay() {
return display;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return "Operation{" +
"symbol='" + symbol + '\'' +
'}';
}
public static Operation getBySymbol(String symbol) {
for (Operation value : values()) {
if (value.getSymbol().equals(symbol)) {
return value;
}
}
return NULL;
}
-
}
class Main{
public static void main(String[] args) {
Operation en = Operation.getBySymbol("+");
System.out.println("en = " + en);
en.setSymbol("-");
System.out.println("en = " + en);
}
}
输出
en = Operation{symbol='+'}
en = Operation{symbol='-'}
虽然不太会有人如此做,但可以造成枚举值被改变,这显然对于枚举的定义来说是错误的!
示例 Enum 优化
-
- 属性 final,使不可变
-
- lombok 的 枚举(简化写法)
-
- 优化每次get循环的getBySymbol方法
@Getter
@ToString
@AllArgsConstructor
public enum Operation {
PLUS("+", "加法"),
MINUS("-", "减法"),
TIMES("*", "乘法"),
DIVIDE("/", "除法"),
NULL("", ""),
;
//符号
private final String symbol;
private final String display;
@Deprecated
public static Operation getBySymbolOld(String symbol) {
for (Operation value : values()) {
if (value.getSymbol().equals(symbol)) {
return value;
}
}
return NULL;
}
private static final Map<String, Operation> enumMap = new HashMap<>();
static {
for (Operation op : Operation.values()) {
enumMap.put(op.toString(), op);
}
}
public static Operation getBySymbol(String symbol) {
return Optional.ofNullable(enumMap.get(symbol)).orElse(NULL);
}
}
其他 enum 知识扩展
-
- 枚举不能继承 ,enum 默认继承了 java.lang.Enum 类(反编译)
public final class Operation extends Enum{
... ...
}
-
- 枚举可以使用抽象方法参数,枚举项必须实现,可以借此实现策略模式.不同枚举定义不同的策略行为.
@Getter
@ToString
@AllArgsConstructor
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;
}
},
NULL("") {
@Override
double apply(double x, double y) {
return 0;
}
},
;
private final String symbol;
/**
* 抽象方法,枚举项必须 override
*/
abstract double apply(double x, double y);
/**
* 默认实现,所有枚举都使用,也可以 override
*/
// double apply(double x, double y) {
// throw new RuntimeException("");
// }
private static final Map<String, Operation> enumMap = new HashMap<String, Operation>();
static {
for (Operation op : Operation.values()) {
enumMap.put(op.symbol, op);
}
}
public static Operation getBySymbol(String symbol) {
return Optional.ofNullable(enumMap.get(symbol)).orElse(NULL);
}
}
-
- 枚举可以实现接口,类似枚举内方法.
需要每个 枚举项都实现接口方法,若接口方法为 default 的,则,枚举项可以使用接口的默认返回值;
public interface Calculator {
double apply(double x, double y);
/**
* 接口默认方法,实现类可以不重写
*/
// default double apply(double x, double y) {
// return 0.0;
// }
}
@Getter
@AllArgsConstructor
public enum Operation implements Calculator {
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;
}
},
NULL("") {
@Override
public double apply(double x, double y) {
throw new RuntimeException("错误");
}
},
;
private final String symbol;
private static final Map<String, Operation> enumMap = new HashMap<String, Operation>();
static {
for (Operation op : Operation.values()) {
enumMap.put(op.symbol, op);
}
}
public static Operation getBySymbol(String symbol) {
return Optional.ofNullable(enumMap.get(symbol)).orElse(NULL);
}
}
可以在枚举类内重写,类似接口实现默认方法,
@Getter
@AllArgsConstructor
public enum Operation implements Calculator {
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;
}
},
NULL(""),
;
private final String symbol;
@Override
public double apply(double x, double y) {
throw new RuntimeException("错误");
}
private static final Map<String, Operation> enumMap = new HashMap<String, Operation>();
static {
for (Operation op : Operation.values()) {
enumMap.put(op.symbol, op);
}
}
public static Operation getBySymbol(String symbol) {
return Optional.ofNullable(enumMap.get(symbol)).orElse(NULL);
}
}
总结
启发于 《Effective Java第二版》,作者Joshua Bloch是Sun公司的高级工程师,也是“Java平台核心组”的设计师。书中指明了在写Java代码时兼顾可维护性与效率的方式,有非常专业的理论知识,强烈推荐。