Best way to create enum of strings?
使用enum类型表示一组字符串的最佳方法是什么?
我试过这个:
1 2 3
| enum Strings{
STRING_ONE("ONE"), STRING_TWO("TWO")
} |
那么,我怎样才能将它们用作Strings?
我不知道您想做什么,但这是我实际翻译示例代码的方法……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| /**
*
*/
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 ;
}
} |
或者,可以为text创建getter方法。
你现在可以做Strings.STRING_ONE.toString();。
- 我不知道这是否是编译器的要求,但private String text应该是最终的。
- @乔纳森,不,我编得很好……
- @乔纳森,如果它是最终的,我认为您不能在构造函数中赋值。你能?
- @Tom&s Narros是的,只要在声明它为final时不给它赋值,您仍然可以在构造函数中为它赋值。
- @精英绅士如果一个枚举常量的值在运行时发生变化会很糟糕,所以即使不需要,final也是最好的。
- @乔纳森:谢谢。这是我从未使用过的东西(总是在声明中初始化最后一个字段)。
- 不要忘记枚举不能用new构造,因为构造函数是private。从本质上讲,对象创建是被禁止的,在这种情况下,final并不是真正必要的。
- @buhakesindi:没错,但意外的是,有人可能会倾向于将setText(String)放在枚举上,这样可以释放地狱:)final类文档说明了您的意图,即它是编译器支持下的常量。如果你使用String常量,你不会把它声明为public static String,对吗?
- @buhake-sindi同样,my-ide表示private对于枚举构造函数是多余的。
- @是真的。默认情况下,enum构造函数是private。
枚举的自定义字符串值
来自http://javahowto.blogspot.com/2006/10/custom-string-values-for-enum.html
JavaEnUM的默认字符串值是其面值或元素名。但是,可以通过重写toString()方法自定义字符串值。例如,
1 2 3 4 5 6 7 8 9 10 11 12 13
| public enum MyType {
ONE {
public String toString () {
return"this is one";
}
},
TWO {
public String toString () {
return"this is two";
}
}
} |
运行以下测试代码将产生此结果:
1 2 3 4 5 6 7 8 9 10
| 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 |
- 这不是一种有效的方法。这将为枚举中的每个值创建一个新的自定义类。在上面的示例中,您将在bin目录中看到以下内容:enumtest$mytype.class enumtest$mytype$1.class enumtest$mytype$2.class,它将快速相加。最好通过将值传递给枚举构造函数来按预期的答案执行。实际上,我不同意重写toString();我认为最好使用一个明确的getter,如getKey(),因为重写toString()可能是枚举的另一个用户所无法预料的。
- 完全同意@mattquigley。这样做可以鼓励用户使用toString来处理不应该使用的内容。如果您需要一个标签,您最好添加一个标签属性
- 另外,也没有其他方法可以绕过(从字符串到枚举对象),这在某些时候可能是必需的。
- 重写ToString不会影响valueOf(),是吗?
使用其name()方法:
1 2 3 4 5 6 7 8 9
| public class Main {
public static void main (String[] args ) throws Exception {
System. out. println(Strings. ONE. name());
}
}
enum Strings {
ONE, TWO, THREE
} |
生成ONE。
- 是的,但是Strings.STRING_ONE.name()产生的是"字符串1",而不是"1"。这根本不是一个好答案。不能有任何不是有效的Java标识符的字符串,等等。
- @马克,是的,它不能处理任何字符。如果OP只需要一个字符,这个解决方案比精英绅士的建议更直接。但事实上:如果字符范围超出了有效Java标识符的范围,则这是不允许的。好点。
- 对于一个枚举有一个内部命名约定是非常合理的,它不同于人们希望用toString()显示的内容(特别是当用户看到输出时),所以我不认为这正是OP所期望的。
- name()的结果可能会受到模糊程序的影响。不久前我也遇到了类似的问题。例如,使用Proguard,您需要解决这个问题。请参见处理枚举类
- 这太棒了。使用的值包括:var_name、var_superlong_但不包括toooooo_long_name等(不包含三个点)
要么将枚举名称设置为与所需的字符串相同,要么更一般地说,可以将任意属性与枚举值相关联:
1 2 3 4 5 6 7
| 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.
} |
将常量放在顶部,方法/属性放在底部是很重要的。
- 还有一个私有的构造函数。
- 枚举构造函数在默认情况下是私有的,不需要访问修饰符。但是,对于访问修饰符来说,这是一个很好的观点,我已经更新了代码,将它们添加到属性和访问器中。
根据您所说的"将它们用作字符串"的含义,您可能不希望在此处使用枚举。在大多数情况下,精英绅士提出的解决方案将允许您通过他们的ToString方法来使用它们,例如在System.out.println(STRING_ONE)或String s ="Hello"+STRING_TWO中,但是当您确实需要字符串(例如STRING_ONE.toLowerCase()时,您可能更喜欢将它们定义为常量:
1 2 3 4
| public interface Strings {
public static final String STRING_ONE ="ONE";
public static final String STRING_TWO ="TWO";
} |
- 实际上,这就是我想要避免的……!
- 事实上,如果他们也想要我的解决方案上的toLowerCase(),他们可以去Strings.STRING_TWO.toString().toLowerCase()。
- 当然,但我并没有把它们当作字符串来解释。由于rrackham似乎不需要这样做,他当然应该使用建议的枚举解决方案。
- 您不应该使用interface来代替带有private构造函数的final类。这是一种令人气馁的做法。
- 这很好,因为您可以在类内使用它,而内部类不能有静态成员。
- 这也适用于switch()声明,而其他解决方案则不适用。
- @mils,使用Enums的解决方案在开关中也能正常工作。我建议只有在直接需要字符串的情况下才使用这个解决方案。
- 枚举是创建常量的最佳方法。最初我们觉得很困难,但一旦你开始这样做,你将永远使用枚举。即使使用反射,也无法更改枚举内的值。
- 真的需要吗?公共静态决赛
- @迪耶拉吉德,不,不是。它们可以是(包)私有的,也可以是受保护的,这取决于它们的使用。但这只适用于绝对需要字符串而不是枚举值的边缘情况。
可以将其用于字符串枚举
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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 ;
}
} |
从主方法调用
1 2 3 4 5 6
| public class Test {
public static void main (String args []){
System. out. println(EnumTest. NAME_ONE. getName());
System. out. println(EnumTest. NAME_TWO. getName());
}
} |
如果不想使用构造函数,并且想为该方法指定一个特殊的名称,请尝试以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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()方法了。它是干净的,可以接受为最佳答案。