java中的枚举,大家应该并不陌生。可enum的特性和用法,可能并不是很了解。enum的出现主要是为了代替public static final的常量的。因为常量有诸多的不便,包括没有命名空间,无法按组隔离,使用容易遗忘,扩展不便,没有编译时错误约束等。于是enum出现了,本文将介绍一些enum巧妙的用法。
enum的特点
enum具有以下特点:
单例,java中实现单例最快捷的方式
本质上是一个final类,并且继承java.lang.Enum
可以在switch判断语句上使用enum,但是并不推荐
可以设置具体的枚举值
利用抽象类构造符合开闭原则的代码
当我们使用enum的时候,大部分人会用switch语句做判断而实现不同枚举使用不用的逻辑。例如以下一个计算器操作的例子:
/**
* 计算器操作枚举
*
* @author zacard
* @since 2015-12-14 10:17
*/
public enum Operation {
PLUS("+"),
MINUS("-"),
MULTIPLY("*"),
DIVISION("/");
private String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
/**
* 测试
*
* @author zacard
* @since 2015-12-14 10:12
*/
public class MyTest {
// 计算
public int apply(Operation operation, int x, int y) {
int result;
switch (operation) {
case PLUS:
result = x + y;
break;
case MINUS:
result = x - y;
break;
case MULTIPLY:
result = x * y;
break;
case DIVISION:
result = x / y;
break;
default:
result = 0;
break;
}
return result;
}
}
这是一个很常见的例子,但是确有极大的隐患。比如计算器操作类增加一个枚举:RADICAL(“√ ̄”)根号,很多客户端的代码就需要改,而且很容易遗忘,因为没有编译时错误的约束。并且大量的switch case语句使得代码冗余,更不符合开闭原则。
只需要对枚举类稍加改造,增加一个抽象方法,即可改变以上种种的问题,代码如下:
/**
* 计算器操作枚举
*
* @author zacard
* @since 2015-12-14 10:17
*/
public enum Operation {
PLUS("+") {
@Override
public int apply(int x, int y) {
return x + y;
}
},
MINUS("-") {
@Override
public int apply(int x, int y) {
return x - y;
}
},
MULTIPLY("*") {
@Override
public int apply(int x, int y) {
return x * y;
}
},
DIVISION("/") {
@Override
public int apply(int x, int y) {
return x / y;
}
},
// 新增加的操作,开根号
RADICAL("√ ̄") {
@Override
public int apply(int x, int y) {
return (int) Math.sqrt(x);
}
};
private String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
// 计算
public abstract int apply(int x, int y);
}
/**
* 测试
*
* @author zacard
* @since 2015-12-14 10:12
*/
public class MyTest {
// 计算
public int apply(Operation operation, int x, int y) {
return operation.apply(x, y);
}
}
当定义了一个抽象方法apply的时候,枚举必须实现这个抽象方法,不然会编译报错,不会造成新增加一个枚举而造成逻辑遗漏的问题。同时,客户端调用的代码页变得异常简单和优雅。
利用接口实现可伸缩的枚举类
我们知道枚举本质是继承Enum的类,并且java是单继承的。因此我们可以使用接口,让枚举实现接口,来构建可伸缩的枚举类,代码如下:
/**
* 计算器操作动作
*
* @author Guoqw
* @since 2015-12-14 13:09
*/
public interface Action {
// 计算
int apply(int x, int y);
}
/**
* @author Guoqw
* @since 2015-12-14 10:17
*/
public enum Operation implements Action {
PLUS("+") {
@Override
public int apply(int x, int y) {
return x + y;
}
},
MINUS("-") {
@Override
public int apply(int x, int y) {
return x - y;
}
},
MULTIPLY("*") {
@Override
public int apply(int x, int y) {
return x * y;
}
},
DIVISION("/") {
@Override
public int apply(int x, int y) {
return x / y;
}
},
RADICAL("√ ̄") {
@Override
public int apply(int x, int y) {
return (int) Math.sqrt(x);
}
};
private String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
这样的好处是当我们要扩充计算器操作枚举类是,来的很方便,代码如下:
/**
* 计算器操作扩展类
*
* @author Guoqw
* @since 2015-12-14 13:13
*/
public enum ExtendOperation implements Action {
// 倒数
RECIPROCAL("1/x") {
@Override
public int apply(int x, int y) {
return 1 / x;
}
};
private String symbol;
ExtendOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}