创建字符串枚举的最佳方法?


364

使enum类型代表一组字符串的最佳方法是什么?

我尝试了这个:

enum Strings{
   STRING_ONE("ONE"), STRING_TWO("TWO")
}

然后如何将它们用作Strings

Answers:


605

我不知道您想做什么,但这就是我实际上翻译示例代码的方式。

package test;

/**
 * @author The Elite Gentleman
 *
 */
public enum Strings {
    STRING_ONE("ONE"),
    STRING_TWO("TWO")
    ;

    private final String text;

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

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

另外,您可以为创建一个getter方法text

你现在可以做 Strings.STRING_ONE.toString();


3
我不知道这是否是编译器要求,但private String text应该是最终的。
乔纳森

7
@TomásNarros是的,只要在声明final时不给它赋值,您仍然可以在构造函数中为其赋值。
乔纳森

28
@精英绅士如果枚举常量的值在运行时更改,那将是不好的,因此即使不是必需的,它final也是最好的。
乔纳森

8
不要忘记Enums不能像构造函数new那样构造private。从本质上讲,禁止创建对象,final在这种情况下实际上并不是必须的。
Buhake Sindi

6
@BuhakeSindi:是的,但是偶然地,有人可能倾向于setText(String)在枚举上放一个,这可能会释放地狱:) final某种文件表明了它在编译器支持下是一个常数。如果要使用String常量,则不会将其声明为public static String,对吗?
TWiStErRob 2014年

104

枚举的自定义字符串值

来自http://javahowto.blogspot.com/2006/10/custom-string-values-for-enum.html

java枚举的默认字符串值是它的面值或元素名称。但是,您可以通过覆盖toString()方法来自定义字符串值。例如,

public enum MyType {
  ONE {
      public String toString() {
          return "this is one";
      }
  },

  TWO {
      public String toString() {
          return "this is two";
      }
  }
}

运行以下测试代码将产生此结果:

public class EnumTest {
  public static void main(String[] args) {
      System.out.println(MyType.ONE);
      System.out.println(MyType.TWO);
  }
}


this is one
this is two

16
不是一种有效的方法。这将为枚举中的每个值创建一个新的自定义类。在上面的示例中,您将在bin目录中看到以下内容:EnumTest $ MyType.class EnumTest $ MyType $ 1.class EnumTest $ MyType $ 2.class这将使实际操作快速完成。最好通过将值传递给枚举构造函数来将其作为期望的答案。我实际上不同意压倒一切toString();我认为最好使用显式的getter,例如,getKey()因为toString()枚举的另一个用户可能会意外覆盖。
马特·奎格利

完全同意@MattQuigley。这样做鼓励用户将toString用于不应使用的东西。如果需要标签,则希望添加标签属性
Sebastien Lorber 2014年

另外,也没有办法(从字符串到枚举对象)在某种程度上需要这样做。
阿德里安·史密斯

覆盖toString不会影响valueOf(),对吗?
Dmitriusan

69

使用其name()方法:

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(Strings.ONE.name());
    }
}

enum Strings {
    ONE, TWO, THREE
}

产量ONE


17
是的,但是Strings.STRING_ONE.name()生成的是“ STRING_ONE”,而不是“ ONE”。这根本不是一个好答案。你不能让这不会是一个有效的Java标识等任何字符串
马克·彼得斯

2
@Mark,是的,它不能处理任何字符。如果OP仅需要一个字符,则此解决方案比The Elite Gentleman建议更直接。但确实如此:如果字符范围超出了有效的Java标识符可以包含的字符范围,那么这是不可行的。好点子。
巴特·基尔斯

对于枚举使用与toString()想要显示的枚举不同的内部命名约定是非常合理的(特别是如果用户看到输出),因此我认为这与OP的含义完全不同。寻找。
Michael McGowan 2010年

17
的结果name()可能会受到混淆器程序的影响。不久前,我遇到了类似的问题。例如,使用Proguard,您需要解决此问题。请参阅处理枚举类
noisecapella 2012年

太好了 与像值作品:VAR_NAME,var_superlong_but_not_toooooo_long_name,甚至等(不特里普尔点)

18

可以将枚举名称设置为与所需的字符串相同,或者更一般而言,可以将任意属性与枚举值相关联:

enum Strings {
   STRING_ONE("ONE"), STRING_TWO("TWO");
   private final String stringValue;
   Strings(final String s) { stringValue = s; }
   public String toString() { return stringValue; }
   // further methods, attributes, etc.
}

重要的是,常量位于顶部,方法/属性位于底部。


并且还有一个私有的构造函数。
Buhake Sindi

1
枚举构造函数默认是私有的,不需要访问修饰符。但这通常是关于访问修饰符的一个好地方,我已经更新了代码以将它们添加到属性和访问器中。
阿德里安·史密斯

15

根据“将它们用作字符串”的含义,您可能不想在此处使用枚举。在大多数情况下,The Elite Gentleman提出的解决方案将允许您通过它们的toString方法使用它们,例如in System.out.println(STRING_ONE)或中String s = "Hello "+STRING_TWO,但是当您确实需要Strings(例如STRING_ONE.toLowerCase())时,您可能更喜欢将它们定义为常量:

public interface Strings{
  public static final String STRING_ONE = "ONE";
  public static final String STRING_TWO = "TWO";      
}

5
实际上,这就是我要避免的事情!
多里(Dori)2010年

实际上,如果他们也想要toLowerCase()我的解决方案,则可以继续Strings.STRING_TWO.toString().toLowerCase()
Buhake Sindi

可以,但是按照我的解释,它不是将它们用作字符串。由于Rrackham似乎不需要使用它,因此他当然应该使用建议的枚举解决方案。
hd42

6
您不应使用带有构造函数interfacefinal类代替private。不鼓励这样做。
Aleks N.

1
@mils,使用枚举的解决方案在开关中同样有效。仅在直接需要字符串的情况下,我才建议此解决方案。
hd42

8

您可以将其用于字符串Enum

public enum EnumTest {
    NAME_ONE("Name 1"),
    NAME_TWO("Name 2");

    private final String name;

    /**
     * @param name
     */
    private EnumTest(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

并从主方法调用

public class Test {
    public static void main (String args[]){
        System.out.println(EnumTest.NAME_ONE.getName());
        System.out.println(EnumTest.NAME_TWO.getName());
    }
}

5

如果你希望使用构造函数,你想有一个特殊的名字的方法,试试这个:

public enum MyType {
  ONE {
      public String getDescription() {
          return "this is one";
      }
  },    
  TWO {
      public String getDescription() {
          return "this is two";
      }
  };

  public abstract String getDescription();
}

我怀疑这是最快的解决方案。不需要使用变量final


但是使用此方法,您仍然必须调用getDescription(),询问者要调用该方法或将其作为常量进行访问。
金斯利·卡吉瓦

我喜欢这个。如果需要接受更多信息会怎样?使用此解决方案,只需添加受保护的抽象方法并对其进行覆盖。无需重写toString()方法。它干净,可以接受为最佳答案。
阿伦杰夫

0

获取并设置默认值。

public enum Status {

    STATUS_A("Status A"),  STATUS_B("Status B"),

    private String status;

    Status(String status) {
        this.status = status;
    }

    public String getStatus() {
        return status;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.