在Java8中重写枚举中的方法有什么原因吗
正如所指出的,lambda提供了一种非常优雅的方式来指定单个枚举值的行为 在Java 8之前,我通常会将其实现为:在Java8中重写枚举中的方法有什么原因吗,java,enums,java-8,Java,Enums,Java 8,正如所指出的,lambda提供了一种非常优雅的方式来指定单个枚举值的行为 在Java 8之前,我通常会将其实现为: enum Operator { TIMES { public int operate(int n1, int n2) { return n1 * n2; } }, PLUS { public int operate(int n1, int n2) { return
enum Operator {
TIMES {
public int operate(int n1, int n2) {
return n1 * n2;
}
},
PLUS {
public int operate(int n1, int n2) {
return n1 + n2;
}
};
public int operate(int n1, int n2) {
throw new AssertionError();
}
}
现在我倾向于使用:
enum Operator {
TIMES((n1, n2) -> n1 * n2),
PLUS((n1, n2) -> n1 + n2);
private final BinaryOperator<Integer> operation;
private Operator(BinaryOperator<Integer> operation) {
this.operation = operation;
}
public int operate(int n1, int n2) {
return operation.apply(n1, n2);
}
}
enum运算符{
次数((n1,n2)->n1*n2),
加上((n1,n2)->n1+n2);
私有最终二进制运算符操作;
专用运算符(二进制运算符操作){
这个操作=操作;
}
公共int操作(int n1、int n2){
返回操作。应用(n1,n2);
}
}
这似乎要优雅得多
我现在想不出重写特定枚举值的方法的理由。所以我的问题是,现在是否有充分的理由在enum
中使用方法重写,还是应该始终首选函数接口 如果您查看在这个enum
场景中使用lambda表达式的优势,您可能会注意到这些优势在Java 8之前的变体中都消失了。它既不比旧的专用enum
变体更具可读性,也不能提高性能。此外,接口BinaryOperator
在Java8之前是不存在的,因此您需要将它添加到代码库中以遵循此方法
在Java8之前的代码中使用这种委托方法的主要原因是,如果您计划很快切换到Java8,那么可以简化迁移
更新您的更新问题: 如果您主要关注Java 8用例,我建议在所有
enum
用例都有不同的行为时始终使用委派方法,这些行为仍然遵循类似的模式,这可以从使用lambda表达式中获益,就像在您的示例中实现操作符时一样
一个反例是enum
,其中大多数都有一个共同的行为,仅在一种或几种情况下会被覆盖。例如:
enum Tokens {
FOO, BAR, BAZ, AND, A, LOT, MORE // etc …
/** Special Token End-Of-File */
EOF {
@Override
public boolean matches(String input, int pos) {
return input.length()==pos;
}
};
// all ordinary tokens have the same behavior
public boolean matches(String input, int pos) {
return input.length()-pos >= name().length()
&& input.regionMatches(pos, name(), 0, name().length());
}
}
我认为在第一个代码中应该是
public int operate
。在一个枚举中,可以有许多方法相互调用。它们的签名可能与任何标准功能接口都不匹配。顺便说一句,在您的第一个代码片段中,您的operate()方法应该声明为抽象的,而不是提供实现。另一种方法(在您的特定示例中)是enum Operator implements BinaryOperator
,然后直接实现apply
。我喜欢使用lambdas的解决方案,它看起来比方法重写干净得多。顺便说一句,您可以使用接口实现此逻辑。谢谢。在发布这篇文章之前,我还没有找到答案——我真的无法在这么短的时间内找到搜索的工作!话虽如此,我不确定你是否真的回答了我的问题。我不是问新方法是否更好(我相信是的)但是否有任何理由重写枚举中的方法?我已经编辑了这个问题,以便更清楚地说明我的问题。这是一个合理的答案,但默认行为可以通过为字段指定默认lambda的空构造函数轻松实现。@sprint:当然,您可以用两种方式实现这两个示例。这不会错的。只是在一种情况下,委托样式在可读性和启动时间方面具有优势,而在另一种情况下,重写样式则领先一小步。我们不是在谈论基本规则。“我会一直用同样的方法”也是一个合理的原则。(尽管我更喜欢的原则是“我迟早会质疑它,即使它是我自己的代码”)我喜欢你的最后一条原则!