簡體   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