枚举构造函数中的非静态方法引用作为参数

Non static method reference in enum constructor as parameter

我正在尝试将一些值映射到应该应用于这些值的函数。 如果简化,我想这样做:

import java.util.function.Supplier;

public enum SomeEnum {
    CASE1 ("val1", this::doAction1),
    CASE2 ("val2", this::doAction1),
    CASE3 ("val3", this::doAction2),
    CASE4 ("val4", this::doAction2);

    String value;
    Supplier<String> action;

    SomeEnum(String value, Supplier<String> action) {
        this.value = value;
        this.action = action;
    }

    private String doAction1() {
        return this.value + "-> action1";
    }

    private String doAction2() {
        return this.value + "-> action2";
    }
}

它无法编译,因为 SomeEnum.this 无法从静态上下文中引用。 我不能使 doAction1 & doAction2 静态化,因为我需要来自实例的值。

这是基于 if-else/switch 的解决方案:

import java.util.function.Supplier;

public enum SomeEnum {
    CASE1 ("val1", SomeEnum.ACTION1),
    CASE2 ("val2", SomeEnum.ACTION1),
    CASE3 ("val3", SomeEnum.ACTION2),
    CASE4 ("val4", SomeEnum.ACTION2);

    final static boolean ACTION1 = true;
    final static boolean ACTION2 = false;

    String value;
    Supplier<String> action;

    SomeEnum(String value, boolean flag) {
        this.value = value;
        this.action = flag ? this::doAction1 : this::doAction2;
    }

    private String doAction1() {
        return this.value + "-> action1";
    }

    private String doAction2() {
        return this.value + "-> action2";
    }
}

此外,我有超过 2 个方法,我需要额外的枚举而不是构造函数中的布尔标志和开关块来映射到函数。 创建此枚举是为了避免在我的遗留世界中出现疯狂的开关块。 如果它再次出现在构造函数中,我将一无所获。

我的主要问题是: 如果可以在构造函数中使用非静态方法引用,为什么我不能将它作为参数传递? 您能否解释一下为什么不允许这样做

enum SomeEnum {
    CASE1 (this::doAction);
    Supplier<String> action;
    SomeEnum(Supplier<String> action) {
        this.action = action;
    }
private String doAction() {
            return "action";
        }
}

什么时候可以

enum SomeEnum {
    CASE1;
    Supplier<String> action;
    SomeEnum() {
        this.action = this::doAction;
    }
    private String doAction() {
        return "action";
    }
}

我找到的唯一解决方案:

import java.util.function.Supplier;

public enum SomeEnum {
    CASE1 ("val1", () -> SomeEnum.doAction1("val1")),
    CASE2 ("val2", () -> SomeEnum.doAction1("val2")),
    CASE3 ("val3", () -> SomeEnum.doAction2("val3")),
    CASE4 ("val4", () -> SomeEnum.doAction2("val4"));

    String value;
    Supplier<String> action;

    SomeEnum(String value, Supplier<String> action) {
        this.value = value;
        this.action = action;
    }

    private static String doAction1(String value) {
        return value + "-> action1";
    }

    private static String doAction2(String value) {
        return value + "-> action2";
    }
}

请您评价一下好不好。为什么不是呢。

你正在尝试实现对我来说似乎根本错误的东西。您知道您可以在枚举中使用抽象方法并为每个常量提供它们的实现吗?

枚举的接口很清楚:一个 String doAction() 方法,本质上就是你作为字段的 Supplier<String>

无论如何,你都会用 getter 放弃这个领域,那你为什么不提供一个方法呢?

enum SomeEnum {
    CASE1("val1") {
        @Override
        public String doAction() {
            return this.value + "-> action1";
        }
    },
    CASE2("val2") {
        @Override
        public String doAction() {
            return this.value + "-> action2";
        }
    };

    String value;

    SomeEnum(String value) {
        this.value = value;
    }

    public abstract String doAction();
}

再提示一下,我喜欢你的问题。

如果您的 enum 的所有元素都具有相同的供应商逻辑,您会更愿意只实现一次供应商的功能,而不是抽象声明。

为什么不试试这个...

public enum SomeEnum {
CASE1("val1"),
CASE2("val2");

private String value;

private SomeEnum(String value) {
    this.value = value;
}

public Supplier<String> doAction() {
    return () -> {
        // Do here anything you need to do...
        return value;
    };
}

}