繁体   English   中英

结合枚举并使用getter返回指定的枚举

[英]Combining enums and using getter to return a specified enum

假设我有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;
}

任何想法返回类型是什么? 我尝试使用Enum而不是Fruits。 当我这样做时,我似乎无法访问getName()方法。

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

所以基本上只需要在其中一个枚举中查找名称AppleAPPLE

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

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

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

  • fvg.getRaw()返回枚举值,例如APPLE

  • fvg.name()返回枚举的字符串名称,例如APPLE

  • fvg.getFriendlyName() :例如Apple

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

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

  • EnumSet.allOf(fvg.getDeclaringClass())) :例如[APPLE,PEAR]

这是代码

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

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

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()
    ... 
}

将Enums本身作为值传递。 然后使用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.BERRY, "Berry");
comboBox.add(lettuces);
comboBox.add(berry);

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

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

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

您可以使用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM