Java 枚举 valueOf() 具有多个值?

发布于 2024-10-03 04:21:52 字数 392 浏览 3 评论 0原文

我在 Java 中使用枚举时遇到问题。 我已阅读有关将值参数分配给枚举的文档。 但是,我的问题是多个值怎么样,可能吗?

这是我想要实现的目标: 我有一个语言枚举。每种语言都由其名称和一些较短的别名表示(并不总是,也不总是相同数量的别名)

这是一个示例:

public enum Language{
English("english", "eng", "en", "en_GB", "en_US"),
German("german", "de", "ge"),
Croatian("croatian", "hr", "cro"),
Russian("russian")
}

我可以像这样定义一个枚举并通过调用 Language.valueOf() 获取正确的枚举值吗???

I have a problem in Java using Enums.
I have read the documentation about assigning value parameters to Enums.
But, my question is what about multiple values, is it possible?

This what I would like to achieve:
I have an Enum for languages. Each language is represented by its name and some shorter aliases (not always, and not always the same number of aliases)

Here is an example:

public enum Language{
English("english", "eng", "en", "en_GB", "en_US"),
German("german", "de", "ge"),
Croatian("croatian", "hr", "cro"),
Russian("russian")
}

Can I just define an Enum like this and get the right enum values by calling Language.valueOf() ???

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦幻的心爱 2024-10-10 04:21:52

这可能与您想要实现的目标类似。

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;
}

This is probably similar to what you're trying to achieve.

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;
    }
}

Remember enums are a class like the others; English("english", "eng", "en", "en_GB", "en_US") is calling the enum constructor.

You could then retrieve the enum value corresponding to a string through a search method (you can put it as a static method in the enum again).

public static Language find(String name) {
    for (Language lang : Language.values()) {
        if (lang.getValues().contains(name)) {
            return lang;
        }
    }
    return null;
}
临走之时 2024-10-10 04:21:52

将字符串映射到枚举值通常是 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 静态方法来测试给定的别名是否是枚举值集的一部分。同时,我们应用了一些良好的命名约定:

  • 枚举值采用大写,以表明它们实际上是静态final(单例实例)。
  • 同时,我们还将所有其他静态决赛全部大写。

请注意,我们不必重复枚举值本身的名称:我们总是自动考虑它自己的名称(添加到 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 静态方法进行查找来以不同的方式实现此目的。这是一种设计选择,但我们可能必须处理其他异常等。

Mapping a string to a enum value, is typically what the valueOf static method is doing for you. So if you want to accomplish this with the use of synonyms, you will have to develop something similar. Because we cannot override a static method, and I do not think we want to in this case, we will name it differently: fromString should be appropriate.

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); 
  } 
} 

As a benefit of this type of implementation we can, as demonstrated, also easily implement the has static method to test if a given alias is part of the enum value set. At the same time, we applied some good naming conventions:

  • the enum values go in uppercase, to indicate that they are in actuality static finals (singleton instances).
  • at the same time, we also put all the other static finals all caps.

Note that we do not have to repeat the name of the enum value itself: we always consider it's own name automatically (gets added to the ALIAS_MAP), and on top we normalize everything to uppercase to make it case insensitive.

Seems big, but while using the enum, it looks pretty:

public void main() {
  Language myLanguage = Language.fromString("en_GB");
  if (myLanguage == Language.ENGLISH) {
    System.out.println("Yes, I know, you understand English!");
  }
} 

The backing container for the aliases is a Map, a HashMap to be more specific. The HashMap provides a fast access path to the aliases, and is also easy to grow. Whenever we think about 'indexing' something, likely a HashMap should be our first choice.

Note that for transparent use, we store both the name of the enum constant itself (retrieved through the name() method), and all the aliases. We could have implemented this differently by first attempting to do the lookup using the built-in valueOf static method. It is a design choice, but we would potentially have to deal with additional exceptions etc.

心意如水 2024-10-10 04:21:52

简而言之,不。

valueOf() 方法的参数只能是枚举常量类型的 String。因此它不能改变,也不能查找可能的值。请参阅 JavaDoc

您需要编写自己的实用程序方法来返回给定值的正确枚举类型。

In short, no.

The parameter for the valueOf() method must be only the String of the enum constant type. So it cannot vary, or lookup possible values. See the JavaDoc.

You need to write your own utility method to return the proper enum type for the given values.

Smile简单爱 2024-10-10 04:21:52

标准化数据:

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),
  // ...
}

等等。

Normalize the data:

public enum LanguageCode
{
  ENGLISH,
  GERMAN,
  CROATIAN,
  RUSSIAN,
  // ...
}
// (add whatever initialization you want to that

Then

public enum Language{
  english(ENGLISH),
  eng(ENGLISH),
  en(ENGLISH),
  en_GB(ENGLISH),
  // ...
}

etc.

雪若未夕 2024-10-10 04:21:52

哇,回复真快:)
谢谢你们。

安迪是对的。我想调用 Language.valueOf("eng") 或 Language.valueOf("english") 并获取 Language.English 作为返回。

我已经有一个实用函数可以做到这一点,但它不是很好。
检查字符串值并返回适当的枚举实例的开关函数。

但是有很多代码重写(我有 cca​​ 30-40 种语言)。
如果我想添加一种语言,我必须将其添加到枚举中,并在实用程序类中实现新的检查。

我会尝试弗拉维奥斯的方法。
只有一个问题。
你的构造函数,不是吗?

Language(List<String> values) {
    this.values = Arrays.asList(values);
}

Wow, really quick reply :)
Thanks guys.

Andy is right. I want to call Language.valueOf("eng") or Language.valueOf("english") and get Language.English as return.

I already have a utility function that does this, but it's not very nice.
Switch function that checks string values and return appropriate enum instance.

But there is a lot of code rewriting (I have cca 30-40 languages).
And if I want to add a language, I have to add it to enum, and implement a new check in the utility class.

I'll try Flavios approach.
Just one question.
Your constructor, shouldn't it be?

Language(List<String> values) {
    this.values = Arrays.asList(values);
}
摇划花蜜的午后 2024-10-10 04:21:52

或者添加一个方法,这样如果结构更复杂,您的枚举和构造函数可以更干净:

public Language getLanguage(String code){
  switch(code){
    case "en":
    case "en_GB":
    ...
    case "eng":
      return ENGLISH;
    case "rus":
    case "russian":
      return RUSSIAN;
  }
}

Alternatively add a method, so your enums and constructor can be more clean if the structure is more complicated:

public Language getLanguage(String code){
  switch(code){
    case "en":
    case "en_GB":
    ...
    case "eng":
      return ENGLISH;
    case "rus":
    case "russian":
      return RUSSIAN;
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文