Объединение перечислений и использование getter для возврата указанного перечисления
Допустим, у меня есть 2 различных набора перечислений: фрукты и овощи.
public static enum Fruits{
APPLE ("Apple"),
PEAR ("Pear");
//constructor
//getName()
...
}
public static enum Vegetables{
CARROT ("Carrot"),
LETTUCE ("Lettuce");
//constructor
//getName()
...
}
Я показываю все это в JComboBox. После того, как кто-то что-то выберет, я хочу использовать метод получения, чтобы вернуть Enum.
Для одного перечисления я бы сделал что-то вроде:
public static Fruits getEnum(String name) {
for(Fruits fruit: Fruits.values()) {
if(name.equals(fruit.getName())) {
return fruit;
}
}
return null;
}
Любые идеи, что тип возврата? Я пытался использовать Enum вместо фруктов. Когда я делаю это, у меня, кажется, нет доступа к методам getName().
5 ответов
Вот еще одна демонстрация того, что вы ищете. Разница между этим и предыдущими решениями заключается в том, что это более общий и многократно используемый шаблон. Это на самом деле выходит за рамки первоначальной проблемы, чтобы показать некоторые другие преимущества этого подхода. Так что вы можете просто комментировать биты, которые вам не нужны. Я также прилагаю модульный тест, чтобы продемонстрировать поведение.
Так что в основном искать имя Apple
или же APPLE
в одном из перечислений просто напишите:
FruitVeg<?> fvg = getEnum("APPLE", Fruits.class, Vegetables.class);
FruitVeg<>
это интерфейс, который позволяет также подключаться внутри Enum, этот интерфейс позволяет делать очень интересные вещи с перечислениями ниже. Вот лишь некоторые вещи, которые вы можете сделать с этим:
Enum.valueOf(fvg.getDeclaringClass(), fvg.name())
: возвращает значение enum, например, APPLEfvg.getRaw()
: возвращает значение enum, например, APPLEfvg.name()
: возвращает строковое имя enum, например, APPLEfvg.getFriendlyName()
Например, Applefvg.getDeclaringClass()
: возвращаетсяClass<Enum<?>>
например, класс ox.dummy.dummyTest$Fruitsfvg.getClass()
: класс 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;
}
Опция 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;
}
и чтобы получить имя enum вы можете использовать этот метод
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 enum как
public static enum FruitsAndVegitables{
APPLE ("Apple" , true),
PEAR ("Pear", true),
CARROT ("Carrot", false),
LETTUCE ("Lettuce", false);
private String name;
private boolean isFurit;
//constructor
//getName()
...
}
Передайте сами перечисления как значения. Затем используйте getSelectedItem, чтобы извлечь выбранный объект, и выполните тест, чтобы увидеть, какой тип объекта.
Сделайте возвращаемый тип вашего метода объектом, а не перечислением определенного типа. Это решило бы вашу проблему.
Тем не менее, я думаю, что ваш подход неверен. Если бы я хотел, чтобы фрукты и овощи отображались в списке и разбивались на категории, я бы создал для этого объект и перечисление для представления типа еды, например:
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
ENUM.
Вы могли бы использовать Object
вместо явного использования Fruit
или же Vegetables
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
Похоже, что вы ищете, это способность применять наследование к enums
, но это невозможно в Java, так как enums
простота расширяется java.lang.Enum
и Java не поддерживает множественное наследование.
Тем не менее, я думаю, что использование " вложенных перечислений" может решить вашу проблему. Под вложенностью я подразумеваю реализацию интерфейса для решения проблемы множественного наследования. Есть несколько разных подходов в ответах в ссылке, я полагаю, одного из них будет достаточно.