我在使用Enums的Java中遇到了问题。 我已阅读有关为Enums分配值参数的文档。 但是,我的问题是多个值是什么,是否可能?
这就是我想要实现的目标: 我有一个语言枚举。每种语言都由其名称和一些较短的别名表示(并非总是如此,并且并不总是相同的别名数)
以下是一个例子:
public enum Language{
English("english", "eng", "en", "en_GB", "en_US"),
German("german", "de", "ge"),
Croatian("croatian", "hr", "cro"),
Russian("russian")
}
我可以像这样定义一个Enum并通过调用Language.valueOf()获得正确的枚举值吗???
答案 0 :(得分:64)
这可能类似于你想要达到的目标。
public enum Language{
English("english", "eng", "en", "en_GB", "en_US"),
German("german", "de", "ge"),
Croatian("croatian", "hr", "cro"),
Russian("russian");
private final List<String> values;
Language(String ...values) {
this.values = Arrays.asList(values);
}
public List<String> getValues() {
return values;
}
}
记住枚举就像其他人一样; English("english", "eng", "en", "en_GB", "en_US")
正在调用枚举构造函数。
然后,您可以通过搜索方法检索与字符串对应的枚举值(您可以将其作为静态方法再次放入枚举中)。
public static Language find(String name) {
for (Language lang : Language.values()) {
if (lang.getValues().contains(name)) {
return lang;
}
}
return null;
}
答案 1 :(得分:15)
将字符串映射到枚举值通常是valueOf
静态方法为您做的事情。因此,如果您想通过使用同义词来实现这一目标,您将不得不开发类似的东西。但是,我们不希望我们可以覆盖静态方法,因此我们只是为此目的命名它:fromString
应该是合适的。
public enum Language {
ENGLISH("eng", "en", "en_GB", "en_US"),
GERMAN("de", "ge"),
CROATIAN("hr", "cro"),
RUSSIAN("ru"),
BELGIAN("be",";-)");
static final private Map<String,Language> ALIAS_MAP = new HashMap<String,Language>();
static {
for (Language language:Language.values()) {
// ignoring the case by normalizing to uppercase
ALIAS_MAP.put(language.name().toUpperCase(),language);
for (String alias:language.aliases)
ALIAS_MAP.put(alias.toUpperCase(),language);
}
}
static public boolean has(String value) {
// ignoring the case by normalizing to uppercase
return ALIAS_MAP.containsKey(value.toUpperCase());
}
static public Language fromString(String value) {
if (value == null) throw new NullPointerException("alias null");
Language language = ALIAS_MAP.get(value.toUpperCase());
if (language == null)
throw new IllegalArgumentException("Not an alias: "+value);
return language;
}
private List<String> aliases;
private Language(String... aliases) {
this.aliases = Arrays.asList(aliases);
}
}
作为此类实现的一个好处,我们可以轻松实现has
静态方法来测试给定别名是否为枚举值集的一部分。与此同时,我们应用了一些很好的命名约定:
请注意,我们不必重复枚举值本身的名称:我们总是自动考虑它自己的名称(添加到ALIAS_MAP),最重要的是我们将所有内容规范化为大写以使其不区分大小写。
看起来很大,但在使用枚举时,它看起来很漂亮:
public void main() {
Language myLanguage = Language.fromString("en_GB");
if (myLanguage == Language.ENGLISH) {
System.out.println("Yes, I know, you understand English!");
}
}
别名的后备容器是Map
,HashMap
更具体。 HashMap
提供了别名的快速访问路径,并且也很容易增长。每当我们考虑“索引”某些内容时,HashMap
可能是我们的首选。
请注意,对于透明使用,我们存储枚举常量本身的名称(通过name()
方法检索)和所有别名。我们可以通过首先尝试使用内置的valueOf
静态方法进行查找来实现这一点。这是一个设计选择,但我们可能不得不处理其他异常等。
答案 2 :(得分:3)
答案 3 :(得分:2)
规范化数据:
public enum LanguageCode
{
ENGLISH,
GERMAN,
CROATIAN,
RUSSIAN,
// ...
}
// (add whatever initialization you want to that
然后
public enum Language{
english(ENGLISH),
eng(ENGLISH),
en(ENGLISH),
en_GB(ENGLISH),
// ...
}
等
答案 4 :(得分:1)
安迪是对的。我想调用Language.valueOf(“eng”)或Language.valueOf(“english”)并将Language.English作为返回。
我已经有一个实用程序功能可以做到这一点,但它不是很好。 切换函数,检查字符串值并返回适当的枚举实例。
但是有很多代码重写(我有cca 30-40语言)。 如果我想添加一种语言,我必须将它添加到枚举中,并在实用程序类中实现一个新的检查。
我会尝试Flavios方法。 只有一个问题。 你的构造函数,不应该是吗?
Language(List<String> values) {
this.values = Arrays.asList(values);
}
答案 5 :(得分:0)
或者添加一个方法,如果结构更复杂,你的枚举和构造函数可以更干净:
public Language getLanguage(String code){
switch(code){
case "en":
case "en_GB":
...
case "eng":
return ENGLISH;
case "rus":
case "russian":
return RUSSIAN;
}
}