Java Enum用条件初始化

时间:2015-10-05 10:25:55

标签: java enums

在某些情况下说我想用以下值初始化我的枚举Foo。

private enum Foo {
  BAR1("1"),
  BAR2("2"),
  BAR3("3")
}

在其他一些情况下,我想要一组不同的值。

private enum Foo {
  BAR1("x"),
  BAR2("y"),
  BAR3("z")
}

然后在其他代码中,它可以使用相同的枚举进行处理。我怎样才能做到这一点?或者还有其他更好的方法来实现我的目标吗?

7 个答案:

答案 0 :(得分:7)

您可以在枚举初始值设定项中使用多个值,然后使用逻辑来选择适当的值:

enum Foo {
  BAR1("1", "x"),
  BAR2("2", "y"),
  BAR3("3", "z");

  private final String first, second;

  private Foo(String first, String second) {
    this.first = first; this.second = second;
  }

  String value(boolean condition) {
    return condition ? first : second;
  }
}

答案 1 :(得分:2)

编写另一个用可变部分包装不可变部分(你的枚举)的类(你的状态可以随时间变化)。

有点像这样:

enum Foo {
    BAR1, BAR2
}

class StatefulFoo {

    private Foo foo;
    private String name;

    public StatefulFoo(Foo foo, String name) {
        this.foo = foo;
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

答案 2 :(得分:1)

由于我不允许发表评论,这里是@Andy的回答

我必须先说:枚举值可能会有所不同,这可能是由于设计不佳造成的。这是一种不好的做法,在多线程环境中,您可能需要在整个枚举中提供一致性等。

//Use this if your enum is system wide, and you make sure you can guarantee
//invariant -> length of array == length of enum.
static String [] sysWideArray = { "a", "b" };

enum Foo2 {
  BAR1,
  BAR2
  ;

  public String getS() { return sysWideArray[this.ordinal()]; }

}

static void printFoo2() {
  for(Foo2 f : Foo2.values()) {
    System.out.println("E: " + f + " getS()=" + f.getS());
  }
}

并在你的主要():

System.out.println("==================");
printFoo2();
System.out.println("==================");
sysWideArray = new String[] { "one", "two" };
printFoo2();

...所以你已经将枚举与其可变部分分开了

答案 3 :(得分:1)

我将此作为第二个答案添加,而不是更新我现有的答案,因为我认为它与人们已经投票的答案太不相同了。

在类中保存选项的替代方法是在外部定义映射。如果您希望能够支持两个以上的映射,这可能是更好的选择。

这样做的好处是可以定义专用于代码特定位的新映射:添加新用例时无需更改枚举的定义。

例如:

EnumMap<Foo, String> numberEnumMapping = new EnumMap<>(Foo.class);
numberEnumMapping.put(Foo.BAR1, "1");
numberEnumMapping.put(Foo.BAR2, "2");
numberEnumMapping.put(Foo.BAR3, "3");
Map<Foo, String> numberMapping = Collections.unmodifiableMap(numberEnumMapping);

EnumMap<Foo, String> letterEnumMapping = new EnumMap<>(Foo.class);
letterEnumMapping.put(Foo.BAR1, "x");
letterEnumMapping.put(Foo.BAR2, "y");
letterEnumMapping.put(Foo.BAR3, "z");
Map<Foo, String> letterMapping = Collections.unmodifiableMap(letterEnumMapping);

// ... More mappings.

(我个人会使用Guava ImmutableMap,但你可能不想使用Guava)。

然后,您可以将Map<Foo, String>传递到需要执行映射的位置:

void doSomething(Foo value, Map<Foo, String> mapping) {
  System.out.println(mapping.get(value));
}

如果您认为更整洁,可以定义界面而不是使用地图:

interface FooStrategy {
  String get(Foo value);
}

但想法是一样的:将FooStrategy传递到您需要将Foo转换为String的地方。

void doSomething(Foo value, FooStrategy mapping) {
  System.out.println(mapping.get(value));
}

答案 4 :(得分:0)

好吧,如果我说得对,你就有Enum with Strings ...... 所以尝试Enum with constructor ..

public enum Foo {
           BAR1("ONE"),
           BAR2("TWO")
           ;

           private final String text;

           /**
            * @param text
            */
           private Strings(final String text) {
               this.text = text;
           }

           /* (non-Javadoc)
            * @see java.lang.Enum#toString()
            */
           @Override
           public String toString() {
               return text;
           }
       }

请记住,枚举器必须具有不同的名称,因此BAR1(&#34; 1&#34;)和BAR1(&#34; x&#34;)不能以相同的数据类型共存...

答案 5 :(得分:0)

你可以让Enum构造函数有2个参数,比如BAR1(&#34; 1&#34;,&#34; x&#34;),然后在Enum中创建一个静态方法,它将返回一个值或另一个取决于参数。

答案 6 :(得分:0)

this解决方案外,您还可以创建界面

interface FooConverter{
 String convert(Foo foo);
}

然后,您可以根据需要提供尽可能多的实现,并且您的枚举可能包含您需要的任意数量的值。您也可以使它更通用,然后您不能仅限于String  和Foo