很多初学者在刚开始使用枚举的时候觉得它只是一个给常量命名的工具,比如 static constant String ENUM_VAL_NAME。
但其实Java的枚举还有很多先进的功能,这些功能可以帮助开发者写出更简洁且不易出错的代码。
接下来我会列举一些Java的高级枚举功能,以及如何利用这些功能来使得开发更高效,更具可读性。
枚举是类
首先,我们要确认一点,枚举是Java的一个类。
比如创建下面一段代码,枚举的基类Enum<E>
public abstract class Enum<E extends Enum<E>>
implements Constable, Comparable<E>, Serializable {
private final String name;
public final String name() {
return name;
}
private final int ordinal;
public final int ordinal() {
return ordinal;
}
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
public String toString() {
return name;
}
public final boolean equals(Object other) {
return this==other;
}
public final int hashCode() {
return super.hashCode();
}
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal – other.ordinal;
}
}
上述代码是一个普通的抽象类,有两个字段,name和ordinal。
由于枚举都是类,所以我们能够为枚举提供实例方法、构造函数和字段,还可以重写 toString()
Java中的Operation枚举
enum Operation {
ADD,
SUBTRACT,
MULTIPLY
}
此枚举表示可以对两个值操作并将产生结果。
一般来说,初学者更偏向于使用switch 语句来完成这个功能,如下代码所示:
public int apply(Operation operation, int arg1, int arg2) {
switch(operation) {
case ADD:
return arg1 + arg2;
case SUBTRACT:
return arg1 – arg2;
case MULTIPLY:
return arg1 * arg2;
default:
throw new UnsupportedOperationException();
}
}
这个实现存在一些问题。
①如果我们向Operation添加新操作,编译器不会通知此switch没有正确处理新的操作。
②遇到default情况,就算我们知道它永远不会发生,这也是必需的。
但还好,Java 8 使用函数式编程为我们提供了一个干净的解决方案。
功能枚举实现
由于枚举是类,我们可以创建一个枚举字段来保存函数。如何来完成这一操作?
首先,让我们将开关放在枚举类中。
enum Operation {
ADD,
SUBTRACT,
MULTIPLY;
public static int apply(Operation operation, int arg1, int arg2) {
switch(operation) {
case ADD:
return arg1 + arg2;
case SUBTRACT:
return arg1 – arg2;
case MULTIPLY:
return arg1 * arg2;
default:
throw new UnsupportedOperationException();
}
}
}
可以做这样的添加:Operation.apply(Operation.ADD, 2, 3);
上述代码中是从 inside 调用方法Operation,可以将其更改为实例方法,并使用this关键字,而不是将所需的Operation作为参数传递。
public int apply(int arg1, int arg2) {
switch(this) {
case ADD:
return arg1 + arg2;
case SUBTRACT:
return arg1 – arg2;
case MULTIPLY:
return arg1 * arg2;
default:
throw new UnsupportedOperationException();
}
}
像这样调用加法操作:Operation.ADD.apply(2, 3);
现在让我们更进一步,通过使用函数式编程完全消除 switch 语句。
enum Operation {
ADD((x, y) -> x + y),
SUBTRACT((x, y) -> x – y),
MULTIPLY((x, y) -> x * y);
Operation(BiFunction<Integer, Integer, Integer> operation) {
this.operation = operation;
}
private final BiFunction<Integer, Integer, Integer> operation;
public int apply(int x, int y) {
return operation.apply(x, y);
}
}
上述代码中做了三件事:
1.添加了一个BiFunction<Integer, Integer, Integer> operation字段。
2.Operation使用BiFunctionarg创建了一个构造函数。
3.调用构造函数BiFunction<Integer, Integer, Integer>并用
lambda指定。该java.util.function.BiFunction operation字段是对带有两个参数的函数(方法)的引用。在上述代码示例中,两个参数都是整数,返回值也是整数。但是Java 参数化类型不支持原语,因此必须使用Integer。
新Operation实现以相同的方式使用:Operation.ADD.apply(2, 3),
但是,这种实现会比switch好一些,因为编译器会在Operation添加新功能时会要求开发者实现新功能。
关键要点
Java 枚举是扩展Enum<T>.
枚举可以有字段、构造函数和实例方法。
Java 枚举字段可以存储函数与 lambda 配合使用,也可以创建一个函数的干净、安全的特定于枚举的实现,并在编译时强制执行(不使用switch)。
以上就是Enum高阶的使用方法,希望对你有帮助。