2015-10-07 2 views
3

Допустим, у меня есть следующие Java перечислениеJava enum autogenerate getInstance метод?

public enum Color { 
    RED(10), 
    GREEN(22), 
    BLUE(33); 

    private int value; 

    Color(int value) { 
    this.value = value; 
    } 

    public int intValue() { 
    return value; 
    } 
} 

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

public static Color getInstance(int value) { 
    switch (value) { 
    case 10: return RED; 
    case 22: return GREEN; 
    case 33: return BLUE; 
    default: throw new IllegalArgumentException("Invalid color value"); 
    } 
} 

Можно этот метод должен быть автогенерирован из среды IDE? (Желательно IntelliJ)?

+2

Сколько таких 'enum' вы ожидаете написать в своей жизни? – Holger

+0

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

+1

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

ответ

0

Если вы используете Java 8, вы можете использовать методы default в interface, чтобы добавить функциональность в любой класс - даже enum s.

Посмотрите here, где я добавляю обратный поиск в enum, просто сделав его implement ReverseLookup.

2

Вместо повторения кода в каждом enum вы можете реализовать центральный метод утилиты для всех видов перечислений с значением int. Это возможно, поскольку enum s может реализовывать интерфейсы, следовательно, вы можете определить единый способ доступа к значению int:

public interface IntValued { 
    int intValue(); 
} 
/** get the particular {@link IntValued} {@code enum} constant. */ 
public static <T extends Enum<T>&IntValued> T get(Class<T> type, int value) { 
    return type.cast(GET.get(type).apply(value)); 
} 
private static ClassValue<IntFunction<Enum>> GET = new ClassValue<IntFunction<Enum>>() { 
    protected IntFunction<Enum> computeValue(Class<?> type) { 
     return prepare(type); 
    } 
}; 
// invoked only once per enum type 
static IntFunction<Enum> prepare(Class<?> type) { 
    Enum[] values=type.asSubclass(Enum.class).getEnumConstants(); 
    if(values.length==0) return i -> null; 
    IntSummaryStatistics s=Arrays.stream(values) 
     .mapToInt(o -> ((IntValued)o).intValue()) 
     .summaryStatistics(); 
    int min=s.getMin(), max=s.getMax(); 
    if((max-min+1)<s.getCount()*2) { 
     Enum[] linear=new Enum[max-min+1]; 
     for(Enum e: values) linear[((IntValued)e).intValue()-min]=e; 
     return i -> i<min||i>max? null: linear[i-min]; 
    } 
    Map<Integer, Enum> map = Arrays.stream(values).collect(
     Collectors.toMap(o -> ((IntValued)o).intValue(), Function.identity())); 
    return map::get; 
} 

Это использует ClassValue, JRE при условии способа ассоциирования пользовательских метаданных к классу. ClassValue заботится о том, чтобы вызвать код инициализации только один раз и до сих пор позволяет выгрузку мусора/разгрузку класса. Приведенный выше код динамически определяет, какую структуру поиска использовать. Если значения int конкретного типа enum плотны, он использует массив, в противном случае он обращается к Map.

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

public enum Color implements IntValued { 
    RED(10), 
    GREEN(22), 
    BLUE(33); 

    private int value; 

    Color(int value) { 
     this.value = value; 
    } 

    public int intValue() { 
     return value; 
    } 
} 

Color color=get(Color.class, 22); 
System.out.println(color); 

Обратите внимание, что это решение, в отличие от сгенерированных switch заявлений, не сломаться, если эти ИНТ значения изменяются.

+0

Ницца! Я полагаю, что вы указали мне некоторое время назад, что 'Class ' имеет метод 'cast'. 'return type.cast (GET.get (type) .apply (value));' будет избегать приведения * evil *. – OldCurmudgeon

+0

@OldCurmudgeon: вы правы; здесь он обращается к тому, что Netbeans не генерирует всевозможные непроверенные предупреждения в своей конфигурации по умолчанию. – Holger

+0

Это кажется излишне сложным. Почему не просто статический метод с сигнатурой, такой как public public Map mapByValue (коллекция значений) ', чье тело является вашим вторым в последнем утверждении? Это даже не нужно указывать на типы перечислений. – VGR

 Смежные вопросы

  • Нет связанных вопросов^_^