11

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

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() 方法。

4

5 回答 5

20

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

所以基本上要查找名称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(): 例如苹果

  • 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;
}
于 2013-11-04T22:50:12.433 回答
3

选项 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()
    ... 
}
于 2013-07-15T03:43:23.020 回答
1

将枚举本身作为值传递。然后使用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

于 2013-07-15T03:44:37.693 回答
0

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

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

于 2013-07-15T03:42:55.040 回答
0

您可以使用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
于 2013-07-15T03:47:52.490 回答