2009-11-03 6 views
1

У меня возникла ситуация, когда я получаю enum из внешней системы и для чего мне нужно вернуть enum. Два перечислений имеют те же буквенные значения в них:Использование instanceof с Java Enums

// externalEnum is guaranteed not to be null 
public static MyEnum enumToEnum(final Enum<? extends Enum<?>> externalEnum) 
{ 
    if(externalEnum instanceof MyEnum) 
    { 
     return (MyEnum)enumType; 
    } 
    else 
    { 
     return MyEnum.valueOf(externalEnum.name()); 
    } 
} 

Однако компилятор визжит следующее:

 
    [javac] found : java.lang.Enum<capture#117 of ? extends java.lang.Enum<?>> 
    [javac] required: myEnum 
    [javac]    if(externalEnum instanceof MyEnum) 

я получил версию этой функции, которая работает просто возвращение MyEnum.valueOf(externalEnum.name()) - это работает и это все, что имеет значение. Тем не менее, я озадачен ошибкой компилятора.

Я пытаюсь понять процесс овеществления дженериков в этом случае. Экземпляр Enum<? extends Enum<?>> или просто Enum<?> может быть MyEnum (при условии, что впоследствии не может быть ничем иным, кроме подтипа первого.)

Так что тест instanceof должен работать, но там, кажется, что-то в родовом определении из Enum (и, возможно, тот факт, что Enums не может быть расширен), что заставляет компилятор пренебрегать этим конкретным утверждением.

Обходной путь для меня прост, но мне нравится хорошо понимать проблемы, и любое понимание этого будет оценено по достоинству.

  • Luis.
+0

Ваше сообщение об ошибке содержит строчный «myEnum», но я не вижу строчный «myEnum» в любом месте вашего кода. Где нижний регистр «myEnum», определенный в вашем коде? Что он делает в этой функции? –

+0

Кроме того, является 'return (MyEnum) enumType;' преднамеренным, или это должно быть 'return (MyEnum) externalEnum'? Когда я меняю его, ваш первый пример отлично подходит для меня. – gustafc

ответ

2

Зачем даже беспокоиться, если оба они одинаковы?

public static MyEnum enumToEnum(final Enum<? extends Enum<?>> externalEnum) 
{ 
    try 
    { 
     return MyEnum.valueOf(externalEnum.name()); 
    } 
    catch (Exception ex) 
    { 
     return MyEnum.UNKNOWN; 
    } 
} 
+0

Duh! Хорошая точка зрения. Удивительно, что я не понимал этого до 7 месяцев :) –

3

Мой (возможно, недостатки) анализ вашей проблемы является то, что две маски в вашем определении типа отделены друг от друга:

Enum<? extends Enum<?>> 

означает «Enum такого типа, который расширяет Enum, что расширяет некоторые неизвестный тип ".

То, что вы хотите, вероятно, больше, как это:

Enum<T extends Enum<T>> 

, который означает «Enum типа, который расширяет Enum себя». Это любопытное рекурсивное определение (которое как-то возвращается к Comparable<T>), но именно так определены Enum.

Конечно, ваш статический метод должен принять параметр типа <T>, чтобы это работало. Попробуйте это:

public static <T extends Enum<T>> MyEnum enumToEnum(final T externalEnum) { 
    if (externalEnum instanceof MyEnum) { 
     return (MyEnum) externalEnum; 
    } else { 
     return MyEnum.valueOf(externalEnum.name()); 
    } 
} 

Edit: исправление ошибки компилятора, вызванные неправильным идентификатором делает код в вопросе компиляции для меня. Поэтому мой анализ определенно испорчен ;-)

1

Я думаю, вы имеете в виду externalEnum, а не enumType в своем первом операторе возврата.

Это исправлено, оно компилируется в Eclipse и с муравьями.

1

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

Экземпляр instanceof будет возвращать значение false, если оба класса загружаются разным загрузчиком классов и/или имеют другую младшую/основную версию. Учитывайте это также.