【问题标题】:Combining enums and using getter to return a specified enum组合枚举并使用getter返回指定的枚举
【发布时间】:2013-07-15 03:29:53
【问题描述】:

假设我有 2 组不同的枚举:水果和蔬菜。

public static enum Fruits{
    APPLE ("Apple"),
    PEAR ("Pear");

    //constructor
    //getName()
    ... 
}
public static enum Vegetables{
    CARROT ("Carrot"),
    LETTUCE ("Lettuce");

    //constructor
    //getName()
    ...
}

我将所有这些都显示在一个 JComboBox 中。有人选择后,我想用getter方法取回Enum。

对于单个枚举,我会执行以下操作:

public static Fruits getEnum(String name) {
  for(Fruits fruit: Fruits.values()) {
    if(name.equals(fruit.getName())) {
      return fruit;
    }
  }
  return null;
}

知道返回类型是什么吗?我尝试使用枚举而不是水果。当我这样做时,我似乎无法访问 getName() 方法。

【问题讨论】:

    标签: java enums


    【解决方案1】:

    这是您正在寻找的另一个演示。此解决方案与以前的解决方案之间的区别在于,此解决方案更通用且可重用。这实际上超出了最初的问题,展示了这种方法的一些其他好处。所以你可能只是评论你不需要的位。我还附上了一个单元测试来演示这种行为。

    所以基本上要在这些枚举之一中查找名称 AppleAPPLE 只需写:

    FruitVeg<?> fvg = getEnum("APPLE", Fruits.class, Vegetables.class);

    FruitVeg<> 是一个接口,它也允许在 Enum 内部点击,这个接口允许用下面的枚举做一些非常有趣的事情。以下是您可以用它做的一些事情:

    • Enum.valueOf(fvg.getDeclaringClass(), fvg.name()): 返回枚举值 例如苹果

    • fvg.getRaw(): 返回枚举值 例如苹果

    • fvg.name() : 返回枚举的字符串名称 例如苹果

    • fvg.getFriendlyName() :例如苹果

    • fvg.getDeclaringClass() : 返回 Class<Enum<?>> 例如类 ox.dummy.dummyTest$Fruits

    • fvg.getClass() : class ox.dummy.dummyTest$Fruits 返回 Class<?>

    • EnumSet.allOf(fvg.getDeclaringClass())) :例如[苹果,梨]

    这里是代码

       @Test
    public void doSimpleTest() throws Exception {
    
        FruitVeg<?> fvg = getEnum("APPLE", Fruits.class, Vegetables.class);
        log.info("{} : {} : {} : {} : {}", fvg.name(), fvg.getFriendlyName(), fvg.getClass(), fvg.getDeclaringClass(), EnumSet.allOf(fvg.getDeclaringClass()));
        log.info("get enum: {} ", Enum.valueOf(fvg.getDeclaringClass(), fvg.name()));
    
    }
    
    
    public interface FruitVeg<T extends Enum<T>> {
        String name();
    
        String getFriendlyName();
    
        Class<T> getDeclaringClass();
    
        T getRaw();
    
    }
    
    enum Fruits implements FruitVeg<Fruits> {
        APPLE("Apple"),
        PEAR("Pear");
    
        Fruits(String friendlyName) {
            this.friendlyName = friendlyName;
        }
    
        private final String friendlyName;
    
        @Override
        public String getFriendlyName() {
            return friendlyName;
        }
        @Override
        public Fruits getRaw() {
            return this;
        }
    }
    
    
    enum Vegetables implements FruitVeg<Vegetables> {
        CARROT("Carrot"),
        LETTUCE("Lettuce");
    
        Vegetables(String friendlyName) {
            this.friendlyName = friendlyName;
        }
    
        private final String friendlyName;
    
        @Override
        public String getFriendlyName() {
            return friendlyName;
        }
    
        @Override
        public Vegetables getRaw() {
            return this;
        }
    }
    
    
    public static FruitVeg<?> getEnum(String name, Class<? extends FruitVeg<?>>... fvgClasses) {
        for (Class<? extends FruitVeg<?>> fruitVegCLass : Arrays.asList(fvgClasses)) {
            for (FruitVeg<?> fvg : fruitVegCLass.getEnumConstants()) {
                if (name.equals(fvg.name()) || name.equals(fvg.getFriendlyName())) {
                    return fvg;
                }
            }
        }
        return null;
    }
    

    【讨论】:

      【解决方案2】:

      选项 1。
      创建一个返回枚举的方法

      public static Enum getEnum(String name) {
          Enum selectedEnum = null;
          for (Fruits fruit : Fruits.values()) {
              if (name.equals(fruit.getName())) {
                  selectedEnum = fruit;
              }
          }
      
          for (Vegetables vegetables : Vegetables.values()) {
              if (name.equals(vegetables.getName())) {
                  selectedEnum = vegetables;
              }
          }
          return selectedEnum;
      }
      

      要获取枚举的名称,您可以使用此方法

      public static String getName(final Enum value) {
          String name = null;
          if (value instanceof Fruits) {
              name = ((Fruits) value).getName();
          } else if (value instanceof Vegetables) {
              name = ((Vegetables) value).getName();
          }
          return name;
      }
      

      选项 2。
      您可以将 2 个枚举组合为

      public static enum FruitsAndVegitables{
          APPLE ("Apple" , true),
          PEAR ("Pear", true),
          CARROT ("Carrot", false),
          LETTUCE ("Lettuce", false);
      
          private String name;
          private boolean isFurit;
          //constructor
          //getName()
          ... 
      }
      

      【讨论】:

      • 由于我不想合并枚举,我想我唯一的选择是 1。
      • @dalawh 如果您发现任何对您有帮助的答案。然后投票并接受该答案,以便将来对其他人有所帮助。我发现您问了很多问题,但没有接受任何答案。因此,如果有任何答案可以解决您的问题,请接受该答案。
      • 所以没有办法在枚举中获取枚举类型而不必组合枚举?
      【解决方案3】:

      将枚举本身作为值传递。然后用getSelectedItem检索选中的对象,做个测试看看对象是什么类型。

      将方法的返回类型设为Object,而不是特定类型的枚举。这将解决您的问题。

      但是,我认为您的方法是错误的。如果我想将水果和蔬菜显示在列表中并分类,我会创建一个对象来执行此操作,并创建一个枚举来表示食物类型,如下所示:

      public enum FoodType{FRUIT, VEGETABLE}
      public class Food{
          FoodType type;
          String name;
          public Food(FoodType type, String name){
              this.type = type;
              this.name = name;
          }
          public String toString(){return this.name;}
      }
      
      //and then when you want to use it...
      Food lettuce = new Food(FoodType.VEGETABLE, "Lettuce");
      Food berry = new Food(FoodType.FRUIT, "Berry");
      comboBox.add(lettuces);
      comboBox.add(berry);
      

      并且仅将 Food 项目添加到您的 JComboBox。选择时返回 Food 项目,并使用 FoodType 枚举测试食物类型。

      【讨论】:

        【解决方案4】:

        听起来您正在寻找的是对enums 应用继承的能力,但这在java 中是不可能的,因为enums 隐式扩展java.lang.Enum 并且java 不支持多重继承。

        不过,我认为使用“nested enums”可以解决您的问题。通过嵌套,我的意思是实现一个接口来解决多重继承问题。链接中的答案有几种不同的方法,我认为其中一种就足够了。

        【讨论】:

          【解决方案5】:

          您可以使用Object 而不是显式使用FruitVegetables

          public static Object getEnum(String name) 
          {    
              for(Fruits fruit: Fruits.values()) 
              {
                  if(name.equals(fruit.getName())) 
                  {
                        return fruit;
                  }
              }
              for(Vegetables vege: Vegetables.values()) 
              {
                  if(name.equals(Vegetables.getName())) 
                  {
                        return vege;
                  }
              }
            return null;
          }
          

          然而,这样做的缺点是您必须将结果进行比较并将结果转换为您想要的结果

          Object o = getEnum("Carrot")
          if(o instanceof Vegetable)
          {
               Vegetable v = (Vegetable)o;
               v.getName();
          }
          //.. and again for fruit
          

          【讨论】:

          • 我希望我不必比较和投射结果。
          • 不幸的是,这个选项意味着我必须为每个不同的枚举创建一个 if 和 else if 语句,并且代码的副本必须驻留在每个枚举中。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-06-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多