Java具有不同值的枚举

时间:2015-11-24 20:24:05

标签: java enums

我使用枚举来定义可以添加到产品中的多个变体(自定义徽标,颜色等)。每个变体都有几个选项(ID,两种语言的描述,在此过程中进行更改,价格等)。它具有进一步定义变体的方法(例如应使用哪种颜色)或覆盖某些选项。一个产品可以具有存储在ArrayList中的零个,一个或多个变体。此外,某种变体可以不止一次应用于一种产品。

只要一切都很好,我只会使用变体。但是如果我不止一次地使用它,似乎所有人都有相同的选择。

示例代码:

TestClass.java:

import java.util.ArrayList;

public class TestClass {
public static void main(String[] args) {
    ArrayList<TestEnum> enums = new ArrayList<>();
    TestEnum enumVar;

    enumVar = TestEnum.TEST1;
    enums.add(enumVar);
    enumVar = null;

    enumVar = TestEnum.TEST2;
    enums.add(enumVar);
    enumVar = null;

    enumVar = TestEnum.TEST2;
    enumVar.setOp1("new op21");
    enumVar.setOp2("new op22");
    enumVar.setOp3("new op23");
    enums.add(enumVar);
    enumVar = null;

    enums.forEach((element) -> {
        System.out.println("op1: " + element.getOp1() + "; op2: " + element.getOp2() + "; op3: " + element.getOp3());
        /*
        Expecting:
        op1: op11; op2: op12; op3: op13
        op1: op21; op2: op22; op3: op23
        op1: new op21; op2: new op22; op3: new op23

        Output:
        op1: op11; op2: op12; op3: op13
        op1: new op21; op2: new op22; op3: new op23
        op1: new op21; op2: new op22; op3: new op23
        */
    });
}
}

TestEnum.java:

public enum TestEnum {
TEST1("op11", "op12", "op13"),
TEST2("op21", "op22", "op23"),
TEST3("op31", "op32", "op33"),
TEST4("op41", "op42", "op43"),
TEST5("op51", "op52", "op53");

private String op1;
private String op2;
private String op3;

TestEnum(String op1, String op2, String op3) {
    this.op1 = op1;
    this.op2 = op2;
    this.op3 = op3;
}

public void setOp1(String op1) {
    this.op1 = op1;
}

public String getOp1() {
    return this.op1;
}

public void setOp2(String op2) {
    this.op2 = op2;
}

public String getOp2() {
    return this.op2;
}

public void setOp3(String op3) {
    this.op3 = op3;
}

public String getOp3() {
    return this.op3;
}
}

是否可以通过枚举实现我的想法?

如果是,我该怎么办?也许有可能在某种状态下创建一个枚举的副本?

5 个答案:

答案 0 :(得分:8)

不,你不能用枚举做到这一点。每个枚举值总是只有一个实例。如果您更改枚举上的数据(例如,使用您的setOpn()方法之一),则会全局更改,因为只有一个。

最好使枚举上的数据不可变。然后,对于变量选项,您可以将ArrayList与具有选项的每个事物相关联,并为其中一个枚举分配。

你可以这样做:

public class ThingWithOptionsAndEnum {
    private final TestEnum myBaseOptions;
    private final ArrayList<String> myAdditionalOptions = new ArrayList<>();

    public ThingWithOptionsAndEnum(final TestEnum base, String... options) {
        this.myBaseOptions = base;
        if (options != null) {
            for (String option : options) {
                myAdditionalOptions.add(option);
            }
        }
    }
}

答案 1 :(得分:8)

此页面上的其他答案可能都是正确的,但可能无法帮助您解决问题。

尝试实现普通的旧类,而不是枚举,但包含clone()方法。然后,您可以创建该类的一些“默认”实例,每个实例代表一个默认产品配置。当用户选择某个产品配置时,您可以在主对象上调用clone(),然后您可以使用常规设置器从此处修改对象。

查看Prototype设计模式。整个想法是使用这些“主”对象来创建可以随后更改的新副本。我想这可能是你想要的更多。 https://en.wikipedia.org/wiki/Prototype_pattern

答案 2 :(得分:6)

不,枚举不适合描述相似但具有不同状态的对象。

枚举常量是静态。您没有TEST1的两个不同实例。你只有一个。在您的示例中引用TEST2的两个列表条目都引用相同的实例。这不是副本,而是第二个参考。

要拥有相似但状态略有不同的实例,您应该声明,而不是枚举。您可以使用枚举来描述变体的类型(例如COLOR_VARIATIONCUSTOM_LOGO)。您可以有两个不同的类来扩展名为Variation的类或直接使用它 - 取决于实现细节是否不同。但是您将使用new Variation(...)或使用静态工厂方法创建Variation的新实例,然后,每个Variation实例的字段中可以有一组不同的值,甚至如果它们都是相同的“变体类型”。

答案 3 :(得分:2)

每个枚举值只有一个实例。将它们视为编译器强制执行的全局变量。

enumVar = TestEnum.TEST2;
enums.add(enumVar);
enumVar = null;

enumVar = TestEnum.TEST2;
enumVar.setOp1("new op21");
enumVar.setOp2("new op22");
enumVar.setOp3("new op23");
enums.add(enumVar);
enumVar = null;

首先,明确地使enumVar引用无效。其次,当您引用TestEnum.TEST2时,您指向两个块中的相同值 - 这意味着您之后对setOp的调用将覆盖之前的值。

答案 4 :(得分:1)

通常,枚举根据定义是不变的。通过在枚举中添加setter,可以使其变为变体。

至于你的问题,这是因为你对数组中的TEST2有相同的引用。由于它是一个参考,第二个和第三个元素是相同的。因此,如果您修改任何TEST2元素,则另一个引用会反映更改。

为了测试这个,您可以将指定行(enumVar.setOp1)从第三个元素切换到第二个元素,您将看到相同的行为。

就像你将枚举转换为对象一样。