java 使用“valueOf”检索枚举会引发RuntimeException -改用什么?

2vuwiymt  于 2023-02-02  发布在  Java
关注(0)|答案(8)|浏览(120)

我有以下枚举

enum Animal implements Mammal {
   CAT, DOG;

   public static Mammal findMammal(final String type) {
      for (Animal a : Animal.values()) {
         if (a.name().equals(type)) {
            return a;
         }
      }
   }
}

我最初使用Enum.valueOf(Animal.class, "DOG");来查找特定的动物。但是,我不知道如果找不到匹配,抛出了一个IllegalArgumentException。我想可能返回了一个null。所以这给我带来了一个问题。如果找不到匹配项,我不想捕获此IllegalArgumentException。我希望能够搜索Mammal类型的所有枚举,但我不想“我不想为Mammal类型的每个枚举实现这个静态的'findMammal'。所以我的问题是,实现这个行为的最好的设计决策是什么?我将调用如下代码:

public class Foo {
   public Mammal bar(final String arg) {
      Mammal m = null;
      if (arg.equals("SomeValue")) {
         m = Animal.findMammal("CAT");
      } else if (arg.equals("AnotherValue") {
         m = Human.findMammal("BILL");
      }
      // ... etc
   }
}

正如你所看到的,我有不同类型的哺乳动物--“Animal”,“Human”,它们都是枚举。我不想为每个哺乳动物枚举都实现“findMammal”。我想最好的办法是创建一个接受哺乳动物参数并搜索它的实用程序类?也许有一个更简洁的解决方案。

ccgok5k5

ccgok5k51#

你可以使用apache EnumUtils库的getEnum方法。如果找不到,它返回枚举或null

EnumUtils.getEnum(Animal.class, "CAT");
vqlkdk9b

vqlkdk9b2#

创建一个HashMap<String, Mammal>怎么样?你只需要做一次...

public class Foo {

  private static final Map<String, Mammal> NAME_TO_MAMMAL_MAP;

  static {
    NAME_TO_MAMMAL_MAP = new HashMap<String, Mammal>();
    for (Human human : EnumSet.allOf(Human.class)) {
      NAME_TO_MAMMAL_MAP.put(human.name(), human);
    }
    for (Animal animal : EnumSet.allOf(Animal.class)) {
      NAME_TO_MAMMAL_MAP.put(animal.name(), animal);
    }
  }

  public static Mammal bar(final String arg) {
    return NAME_TO_MAMMAL_MAP.get(arg);
  }
}

注:

  • 如果名称不存在,则返回null
  • 这不会检测到名称冲突
  • 您可能希望使用某种描述的不可变Map(例如,通过Guava
  • 您可能希望编写一个实用程序方法来为通用枚举创建一个不可变的名称到值Map,然后合并这些Map:)
f5emj3cl

f5emj3cl3#

如果你不想触及每一个Enum(可以理解),那么实用方法是一个不错的选择。我理解你不想在代码中捕捉异常,但是在方法中捕捉应该没问题:

public static <T extends Enum<T>> T findEnumValue(Class<T> type, String name) {
    if (name == null)
        return null;
    try {
        return Enum.valueOf(type, name.toUpperCase());
    } catch (IllegalArgumentException iae) {
        return null;
    }
}
7tofc5zh

7tofc5zh4#

你可以使用guava库。Enums类允许:

Enums.valueOfFunction(MyEnum.class).apply(id);
1aaf6o9v

1aaf6o9v5#

我不明白这个问题,但我还需要一个返回null而不是抛出异常的valueOf,所以我创建了这个实用程序方法:

public static <T extends Enum<T>> T valueOf(T[] values, String name)
{
    for (T value : values) {
        if (value.name().equals(name)) {
            return value;
        }
    }
    return null;
}

你可以这样称呼它:

Animal a = valueOf(Animal.values(), "CAT");
4urapxun

4urapxun6#

你的代码中有一个错误。如果你需要你的函数在找不到东西的时候返回null,那么简单地返回它:

enum Animal implements Mammal {
   CAT, DOG;

   public static Mammal findMammal(final String type) {
      for (Animal a : Animal.values()) {
         if (a.name().equals(type)) {
            return a;
         }
      }
      return null; // this line works if nothing is found.
   }
}

如果您犯了同样的错误,却忘记为每一种可能的情况创建一些返回值,那么没有任何技术可以提供帮助。
您的选择:Enum-EnumMaps-HashMap依赖于你的数据的动态性。Enums常量不能在运行时创建。另一方面,你不需要在运行时检查很多东西-编译器会做的。而且你很可能会忘记检查一些东西。Jon Skeet轻松管理的东西可能会让你头疼。

c8ib6hqw

c8ib6hqw7#

如果你能说

m = Animal.findMammal("CAT");

你为什么不能说

m = Animal.CAT;

“CAT”无论如何都必须与枚举名称匹配,在您的示例中,“CAT”不是从参数派生的,而是硬编码的。

更新(可能更接近问题的要点)

有点复杂,但是...

public interface Mammal{

    public void doMammalStuff();

    public static interface Finder{
        public Mammal find(String name, Class<Enum<?>> enumType);
    }

    public static Finder FINDER = new Finder(){
        public Mammal find(String name, Class<Enum<?>> enumType) {
            return enumType.forName( name );
    };
    };
}

然后你可以打电话

Mammal m = Mammal.FINDER.find( "CAT", Animal.class );

find()的实现看起来可能有所不同(例如,没有抛出异常)。

qacovj5a

qacovj5a8#

import com.google.common.base.Enums;

return Enums.getIfPresent(Animal.class, value).or("default_animal"));

return Enums.getIfPresent(Animal.class, value).orNull());

if (Enums.getIfPresent(Animal.class, value).isPresent()) {
    // take action
}

相关问题