JAVA枚举,比你想象的有用!我经常发现自己在Java中使用枚举来表示对象的一组潜在值。在编译时确定类型可以具有哪些值的能力是赋予代码结构和意义的强大能力。当我第一次了解枚举时,我认为它们只是一种命名常量的工具,可以很容易地用静态常量字符串ENUM_VAL_NAME代替。后来我发现我错了。事实证明,Java枚举具有相当高级的功能,可以使代码干净、不易出错且功能强大。让我们看一下Java中的一些高级枚举功能,以及如何使用它们来使代码更简单、更易读。枚举是类!在Java中,枚举是对象的子类。让我们看一下所有枚举的基类Enum(为简洁起见进行了修改)。publicabstractclassEnum>implementsConstable,Comparable,Serializable{privatefinalStringname;publicfinalStringname(){returnname;}privatefinalintordinal;publicfinalintordinal(){returnordinal;}protectedEnum(Stringname,intordinal){this.name=name;this.ordinal=ordinal;}publicStringtoString(){returnname;}publicfinalbooleanequals(Objectother){returnthis==other;}publicfinalinthashCode(){returnsuper.hashCode();}publicfinalintcompareTo(Eo){Enum>other=(Enum>)o;Enumself=this;if(self.getClass()!=other.getClass()&&//optimizationself.getDeclaringClass()!=other.getDeclaringClass())thrownewClassCastException();returnsself.ordinal-other。ordinal;}}如我们所见,这基本上只是一个普通的抽象类,有两个字段,name和ordinal。所以枚举是类,所以它们具有常规类的许多属性。我们可以为枚举提供实例方法、构造函数和字段。我们可以覆盖toString(),但不能覆盖hashCode()或equals(Objectother)。接下来看我们的枚举例子,OperationenumOperation{ADD,SUBTRACT,MULTIPLY}这个枚举表示可以对两个值执行一个Operation,会产生一个结果。您对如何实现这一点的最初想法可能是使用switch语句,如下所示:;default:thrownewUnsupportedOperationException();}当然这种方式会有一些问题。第一个问题是,如果我们向枚举操作添加新操作,编译器不会通知我们开关没有正确处理新操作。更糟糕的是,如果一个懒惰的开发人员在另一个类中复制或重写这段代码,我们可能无法更新它。第二个问题是默认,这是每个程序都需要的,即使我们知道它永远不会发生在正确的代码中。这是因为Java编译器知道上面的第一个问题,并希望确保我们可以在我们不知情的情况下处理向Operation添加新枚举。幸运的是,Java8为我们提供了一个干净的函数式编程解决方案。函数枚举实现因为枚举是类,我们可以创建一个枚举字段来保存执行操作的函数。但在我们找到解决方案之前,让我们看看一些重构。首先,让我们把开关放在枚举类中。enumOperation{ADD,SUBTRACT,MULTIPLY;publicstaticintapply(Operationoperation,intarg1,intarg2){switch(operation){caseADD:returnarg1+arg2;caseSUBTRACT:returnarg1-arg2;caseMULTIPLY:returnarg1*arg2;default:thrownewUnsupported}Operation}Ex;这可以这样完成:Operation.apply(Operation.ADD,2,3);由于我们现在是从Operation调用方法,我们可以将其更改为实例方法并使用this代替Operation.apply(),像这样:publicintapply(intarg1,intarg2){switch(this){caseADD:returnarg1+arg2;caseSUBTRACT:returnarg1-arg2;caseMULTIPLY:returnarg1*arg2;default:thrownewUnsupportedOperationException();}}像这样使用:Operation.ADD。应用(2、3);看起来更好。现在让我们更进一步,使用函数式编程完全消除switch语句。enumOperation{ADD((x,y)->x+y),SUBTRACT((x,y)->x-y),MULTIPLY((x,y)->x*y);Operation(BiFunctionoperation){this.operation=operation;}privatefinalBiFunctionoperation;publicintapply(intx,inty){returnoperation.apply(x,y);}}我这里做的是:添加一个字段BiFunction使用BiFunction为Operation创建构造函数。调用枚举定义中的构造函数并使用lambda指定BiFunction。java.util.function.BiFunction操作字段是对带有两个参数的函数(方法)的引用。在我们的例子中,两个参数都是int类型,返回值也是int类型。不幸的是,Java参数化类型不支持原语,因此我们必须使用Integer。因为BiFunction是用@functioninterface注释的,所以我们可以使用Lambda表示法定义一个。因为我们的函数有两个参数,所以我们可以使用(x,y)指定它们。然后我们定义一个使用->x+y返回值的单行方法。这相当于下面的方法,只是更简洁。classAdderimplementsBiFunction{@OverridepublicIntegerapply(Integerx,Integery){returnx+y;}}我们新的Operation实现做同样的事情:Operation.ADD.apply(2,3);。但是,这种实现更好,因为编译器会告诉我们何时添加了新的Operation,这需要我们更新新函数。如果没有这个,如果我们不记得在添加新操作时更新switch语句,我们就有可能得到UnsupportedOperationException()。要点Enum枚举是Enum的扩展类。枚举可以有字段、构造函数和实例方法。Enum枚举字段可以存储函数。与lambda一起使用以创建枚举特定函数的干净、安全的实现,并在编译时强制执行它们(而不是使用开关)。下面是这个例子的GitHub地址。(https://github.com/alex-power/java-enum-example)本文参考:https://medium.com/javarevisited/advanced-java-enum-features-you-need-to-know-b516a191c7e2