Как преобразовать значение из одного перечисления в другое в Java? - PullRequest
11 голосов
/ 02 сентября 2011

Как я могу привести значение из Enum1 в Enum 2 в Java? Вот пример того, что я пытаюсь сделать:

public enum Enum1 {
  ONE,
  TWO,
  THREE;
}

public enum Enum2 {
  FOUR,
  FIVE,
  SIX;
}

Итак, я хочу сделать что-то вроде этого:

Enum2 en2 = (Enum2)ONE;

Возможно ли это и как я могу это сделать?

Заранее спасибо!

Ответы [ 11 ]

19 голосов
/ 02 сентября 2011

Вы не можете разыгрывать одно перечисление в другое, однако каждое перечисление имеет гарантированный порядок, и вы можете легко перевести одно перечисление в другое (сохраняя порядок).Например:

enum E1 {
    ONE, TWO, THREE,
}

enum E2 {
    ALPHA, BETA, GAMMA,
}

мы можем перевести E1.TWO в / из E2.BETA следующим образом:

static E2 E1toE2(E1 value) {
    return E2.values()[value.ordinal()];
}

static E1 E2toE1(E2 value) {
    return E1.values()[value.ordinal()];
}
7 голосов
/ 02 сентября 2011

Это невозможно.Enum1 и Enum2 - это разные типы, не имеющие ничего общего.

5 голосов
/ 10 ноября 2016

Ответ на этот вопрос может зависеть от того, что ожидается от «кастинга»:

Кастинг по порядковому положению

В представленном примере нет никакого сходства между наборами значений в двух перечислениях, поэтому я предполагаю, что намерение состояло в том, чтобы перевести по порядковому положению, что Enum1.ONE => Enum2.FOUR, Enum1.TWO => Enum2.FIVE и Enum1.THREE => Enum2.SIX. Это можно сделать следующим образом:

Enum2 en2 = Enum2.values()[Enum1.ONE.ordinal()];

Следующий естественный вопрос - как это можно расширить на универсальную функцию, которая будет делать то же самое для любых двух типов enum. Не для слабонервных, но следующие будут делать работу (для этого требуется гуава):

public <F extends Enum<F>> F castByOrdinal(Enum<?> e, Class<F> fClass) {
    return Iterators.get(EnumSet.allOf(fClass).iterator(), e.ordinal());
}

Если библиотека Google Guava отсутствует, это можно сделать вручную еще в нескольких строках кода:

public <F extends Enum<F>> F castByOrdinal(final Enum<?> e, final Class<F> fClass) {
    final Iterator<F> iter = EnumSet.allOf(fClass).iterator();
    int count = 0;
    F fValue = null;
    while (count <= e.ordinal()) {
        if (!iter.hasNext()) {
            return null; // Or throw exception if preferred e.g. IndexOutOfBoundsException
        }
        fValue = iter.next();
        count++;
    }

    return fValue;
}

Пример использования:

Enum2 en2 = castByOrdinal(Enum1.ONE, Enum2.class);

Приведение по именам общих перечисляемых значений

Существует еще один возможный способ приведения между перечислениями, которые имеют одни и те же имена значений:

например:

enum Shape {
    TRIANGLE, SQUARE, PENTAGON, HEXAGON, UNKNOWN, NOT_APPLICABLE
}

enum Size {
    SMALL, MEDIUM, LARGE, UNKNOWN, NOT_APPLICABLE
}

Это приведение будет работать только для общих значений (т. Е. UNKNOWN и NOT_APPLICABLE выше) и может быть выполнено следующим образом:

Size size = Size.valueOf(Shape.UNKNOWN.name());

Это вызовет исключение IllegalArgumentException, если имя значения не существует в целевом перечислении. На этот раз универсальный метод может быть немного проще:

public <F extends Enum<F>> F castByName(final Enum<?> e, final Class<F> fClass) {
    return F.valueOf(fClass, e.name());
}

Пример использования:

Size size = castByName(Shape.UNKNOWN, Size.class);
5 голосов
/ 02 сентября 2011

Вы можете определить метод в Enum1 для возврата соответствующего Enum2:

enum Enum1 {
    ONE {
        @Override
        public Enum2 toEnum2() {
            return Enum2.ALFA;
        }
    },
    TWO {
        @Override
        public Enum2 toEnum2() {
            return Enum2.BETA;
        }
    }
    ,
    THREE {
        @Override
        public Enum2 toEnum2() {
            return Enum2.GAMMA;
        }
    }
    ;

    public abstract Enum2 toEnum2();
}

enum Enum2 {
    ALFA, BETA, GAMMA;
}

или, немного более читабельно (IMO):

enum Enum1 {
    ONE(Enum2.ALFA), 
    TWO(Enum2.BETA), 
    THREE(Enum2.GAMMA);

    private final Enum2 enum2;

    private Enum1(Enum2 enum2) {
        this.enum2 = enum2;
    }

    public Enum2 toEnum2() {
        return enum2;
    }
}

enum Enum2 {
    ALFA, BETA, GAMMA;
}

EDIT:
если вам нужно поддерживать разделение двух перечислений, создайте карту, содержащую сопоставление от Enum1 к Enum2 (в третьем служебном классе).

3 голосов
/ 30 сентября 2014

Несмотря на то, что этот билет был активен довольно давно, я добавляю еще одну возможность:

Вы также можете создать карту, например, так:

HashMap<Enum1, Enum2> e1ToE2 = new HashMap<Enum1, Enum2>();
e1ToE2.put(Enum1.ONE, Enum2.FOUR);
e1ToE2.put(Enum1.TWO, Enum2.FIVE);

использование

Enum2 e2 = e1ToE2.get(Enum1.ONE);

(+) вам не нужно перепроверять порядок элементов

(+) легко читаемый

(+) быстро

(-)требуется место

Поправь меня, если я ошибаюсь :)

3 голосов
/ 02 сентября 2011

Вы не можете; но вы можете создать статический метод в ваших перечислениях с кодом перевода. Но у вас должно быть четкое представление о правилах, которые вы хотите реализовать.

3 голосов
/ 02 сентября 2011

Вы не можете сделать это, потому что они являются объектами разных классов.

Вы можете преобразовать из одного в другой на основе порядкового значения или имени, но я быподвергните сомнению дизайн любой программы, которая должна была сделать это.

2 голосов
/ 02 сентября 2011

Операция приведения невозможна, но вы можете написать статическую функцию-член для enum1, которая приводит enum2 к enum1:

public static Enum1 fromEnum2(Enum2 enum2) {
    ...
}

Кстати, вы можете назначить идентификатор каждой константе обоих перечисленийчто упрощает реализацию.

Здесь учебник по перечислениям.

0 голосов
/ 02 января 2017

Вы не можете разыграть одно перечисление в другое, однако каждое перечисление имеет гарантированный порядок, и вы можете легко перевести одно перечисление в другое

0 голосов
/ 10 ноября 2016

Вы можете сделать это простым способом:

 public enum number{one,two};
        public enum number1{one,two};
        public void  castTonumber1(number number){

            number1 num1 = number1.valueOf(number.one.toString());
           System.out.println( "value of number 1 is " + num1);

        }*
...