Java 枚举详细信息(枚举基本使用高级使用枚举扩展)
JAVA 枚举详解
java 枚举类型的基本想法非常简单:这些类通过共有的静态final域为每个枚举常量导出一个实例。枚举类型没有可以访问的构造器,所以它是真的final类。客户端不能创建枚举类型的实例,也不能对它进行扩展,因此不存实例,而只存在声明过程的枚举常量。也就是枚举类型是实例受控的。它们是单例(Singleton)的范型化,本质上是单元素的枚举。
枚举类型保证了编译时的类型安全。包含同名常量的多个枚举类型可以在一个系统中和平共处。因为每个类型都有自己的命名空间。可以新增或者重新排列枚举类型中的常量,而无需重新编译它的客户端代码。
枚举类型可以添加任意的方法和域,并实现任意的接口。它们提供了所有的Object方法的高级实现,实现了Comparable和Serializable接口,并针对枚举类型的可任意改变性提供了序列化方法。
举个例子,如定义一个状态类型枚举类,代码如下:
public enum StatusPublicEnum {
FAIL("失败", "300", "认证系统"),
OK("成功", "200", "认证系统");
private final String msg;
private final String status;
private final String code;
StatusPublicEnum(String msg, String status, String code) {
this.msg = msg;
this.status = status;
this.code = code;
}
public String toJson() throws Exception {
JSONObject jsonObject = new JSONObject();
jsonObject.put("msg",this.msg);
jsonObject.put("status",this.status);
jsonObject.put("code",this.code);
return jsonObject.toCompactString();
}
public static void main(String[] args) throws Exception {
System.out.println(StatusPublicEnum.FAIL.toJson());
System.out.println(StatusPublicEnum.OK.toJson());
}
}
说明:在枚举类型StatusPublicEnum
中添加了toJson
方法,该方法返回了枚举类中定义三个属性的JSON串。我们使用时可以直接调用StatusPublicEnum.OK.toJson()
方法,返回OK枚举对象的JSON串。返回结果如下
{"msg":"失败","status":"300","code":"认证系统"}
{"msg":"成功","status":"200","code":"认证系统"}
StatusPublicEnum实例对于大多数枚举类型来说足够了,但是我们有时候会需要更多的方法。每个常量关联了不同的数据类型,但有时需要将不同的行为与每个常量关联起来。例如我们编写一个枚举类型,来表示计算器的四大基本操作,你想要提供一个方法来执行每个常量所表示的算术运算。有一种方式是通过启用枚举的值来实现。
/**
* 枚举计算类
*/
public enum Operation {
PLUS, MINUS, TIMES, DIVIDE;
public 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);
}
public static void main(String[] args) {
System.out.println(Operation.PLUS.apply(2, 3));
}
}
这段代码能用,但是不太好看。如果没有 throw 语句,它就不能进行编译,虽然从技术角度来看代码的结束部分是可以执行的,但是实际上是不可能执行到这行代码的。更糟糕的是,这段代码很脆弱。如果新增一个枚举常量,却忘记给switch添加相应的条件,枚举类型可以编译,但是运行新的枚举常量时,运行就会失败。
让我们改进这个方法,在枚举类型中声明一个抽象的apply方法,并在特定于常量的类主体中,用具体的方法覆盖每个常量的抽象apply方法。这种方法被称为特定于常量的方法实现。
/**
* 枚举计算类
*/
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;
}
};
private final String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
public abstract double apply(double x, double y);
@Override
public String toString() {
return symbol;
}
public static void main(String[] args) {
double x = 4;
double y = 2;
for (Operation operation : Operation.values()) {
System.out.printf("%f %s %f = %f%n",
x, operation, y, operation.apply(x, y));
}
}
}
通过接口扩展枚举
虽然枚举类型是不可扩展的,但是接口类型确实可扩展的,它是用来表示API中的操作的接口类型。你可以定义另一个枚举类型,它实现这个接口,并用这个新类型的实例代替基本类型。
定义接口:
public interface IOperation {
double apply(double x, double y);
}
枚举实现:
/**
* 枚举计算类
*/
public enum Operation implements IOperation{
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;
}
};
private final String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
public static void main(String[] args) {
double x = 4;
double y = 2;
for (Operation operation : Operation.values()) {
System.out.printf("%f %s %f = %f%n",
x, operation, y, operation.apply(x, y));
}
}
}
扩展实现乘积运算:
public enum ExtOperation implements IOperation {
EXP("^") {
@Override
public double apply(double x, double y) {
return Math.pow(x, y);
}
};
private final String symbol;
ExtOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return this.symbol;
}
//入参实现IOperation接口并且是枚举类型。这个可以将该限定去掉,只要实现IOperation接口即可。
private static <T extends Enum<T> & IOperation> void test(Class<T> tClass, double x,
double y) {
for (IOperation operation : tClass.getEnumConstants()) {
System.out.printf("%f %s %f = %f%n",
x, operation, y, operation.apply(x, y));
}
}
public static void main(String[] args) {
test(ExtOperation.class,2,3);//使用扩展实现枚举对象
test(Operation.class,2,3);//使用默认的实现
}
}
更多内容请查看 Julywhj的博客期待您的光顾。
上一篇: 理解列举的概念及其存在的意义
下一篇: 解释枚举在 C++ 中的使用