是否有任何理由覆盖 Java 8 中枚举中的方法

Is there any reason to override methods in enums in Java 8

正如所指出的 here 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 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 中使用方法覆盖,或者应该始终首选功能接口?

如果您查看 this answer,其中总结了在此 enum 场景中使用 lambda 表达式的优势,您可能会注意到这些优势在 Java 8 之前的变体中都消失了。它既不比旧的专用 enum 变体更具可读性,也没有提高性能。此外,interface BinaryOperator 在 Java 8 之前不存在,所以它是另一个 class 您需要添加到您的代码库以遵循此方法。

如果您打算很快切换到 Java 8,那么在 Java 8 之前的代码中使用这种委托方法的主要原因是为了简化迁移。


更新您的问题:

如果您主要关注 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());
    }
}