Базовое приложение
Пользователи
Настройки форм
Права доступа
Ролевой механизм
Загрузка модулей410013796724260
Перечисления enumПри программировании часто необходимо использовать ограниченное множество допустимых значений для некоторого типа данных. Так, например, день недели может иметь 7 разных значений, месяцев в году не более 12, и всего 4 времени года. Для решения подобных задач во многих языках программирования предусмотрен специальный тип данных - перечисление (enum). В Java перечисление enum появилось не сразу только в версии Java 5. Синтаксис перечисления enumОписание с помощью enum типа данных Season для хранения времени года можно представить в следующем виде :
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
Простой пример использования enum :
Season season = Season.WINTER;
if (season == Season.WINTER)
season = Season.SPRING;
System.out.println(season.name());
В результате выполнения данного кода в консоль будет выведен текст SPRING. Перечисление enum - это классПри объявлении переменной типа enum неявно создается класс производный от java.lang.Enum. Условно рассматриваемая конструкция enum Season { ... } эквивалентна class Season extends java.lang.Enum { ... }. Явным образом наследоваться от java.lang.Enum не позволяет компилятор. Но то, что enum наследуется, легко убедиться с помощью reflection: System.out.println(Season.class.getSuperclass()); В консоль будет выведено : class java.lang.Enum Таким образом наследование за разработчика автоматически выполняет компилятор Java. Далее в тексте enum-классом будет называться класс, созданный компилятором для реализации перечисления, а возможные значения перечисляемого типа - элементами enum'a. Элементы перечисления enumЭлементы enum Season (WINTER, SPRING и т.д.) - это статически доступные экземпляры enum-класса Season. Их статическая доступность позволяет выполнять сравнение с помощью оператора сравнения ссылок ==. Например :
Season season = Season.SUMMER;
if (season == Season.AUTUMN)
season = Season.WINTER;
Название и порядковый номер элемента enumПример использования методов enum для извлечения информации об объекте :
Season season = Season.WINTER;
System.out.println("season.name() = " + season.name() + ", season.toString() = " + season.toString() +
", season.ordinal() = " + season.ordinal());
В консоле будет представлено: season.name() = WINTER, season.toString() = WINTER, season.ordinal() = 0 В примере использованы методы name(), toString() и ordinal(). Семантика методов - очевидна. Следует обратить внимание, что данные методы enum-класс наследует от класса java.lang.Enum Получение елемента enum по строковому представлению его имениДовольно часто возникает задача необходимости получения элемента enum по его строковому представлению. Для этих целей в каждом enum-классе компилятор автоматически создает специальный статический метод : public static EnumClass valueOf (String name), который возвращает элемент перечисления EnumClass с названием, равным name. Например: String name = "WINTER"; Season season = Season.valueOf(name); В результате выполнения кода переменная season будет равна Season.WINTER. Получение элементов перечисленияЕсли необходимо получить список всех элементов enum-класса во время выполнения, то для этих целей в следует использовать метод: public static EnumClass[] values(). Например: System.out.println(Arrays.toString(Season.values())); В консоль будет выведено: [WINTER, SPRING, SUMMER, AUTUMN] Необходимо иметь в виду, что ни метод valueOf(), ни метод values() не определены в классе java.lang.Enum. Они автоматически добавляются на этапе компиляции enum-класса. Добавление методов в enum-классМожно добавлять собственные методы как в enum-класс, так и в его элементы:
enum Direction {
UP, DOWN;
public Direction opposite() { return this == UP ? DOWN : UP; }
}
Тот же пример, но с полиморфизмом:
enum Direction {
UP {
public Direction opposite() { return DOWN; }
},
DOWN {
public Direction opposite() { return UP; }
};
public abstract Direction opposite();
}
Наследование в enumС помощью enum в Java можно реализовать иерархию классов, объекты которой создаются в единственном экземпляре и доступны статически. При этом элементы enum могут содержать собственные конструкторы. Пример:
enum Type {
INT(true) {
public Object parse(String string) {
return Integer.valueOf(string);
}
},
INTEGER(false) {
public Object parse(String string) {
return Integer.valueOf(string);
}
},
STRING(false) {
public Object parse(String string) {
return string;
}
};
boolean primitive;
Type(boolean primitive) {
this.primitive = primitive;
}
public boolean isPrimitive() {
return primitive;
}
public abstract Object parse(String string);
}
Здесь объявляется перечисление Type с тремя элементами INT, INTEGER и STRING. Компилятор создаст следующие классы и объекты:
Три производных класса будут созданы с полиморфным методом Object parse (String) и конструктором Type (..., boolean). При этом объекты классов INT, INTEGER и STRING существуют в единственном экземпляре и доступны статически. В этом можно убедиться, выполнив следующий код : System.out.println(Type.class); System.out.println(Type.INT .getClass() + " " + Type.INT .getClass().getSuperclass()); System.out.println(Type.INTEGER.getClass() + " " + Type.INTEGER.getClass().getSuperclass()); System.out.println(Type.STRING .getClass() + " " + Type.STRING .getClass().getSuperclass()); Результат выполнения кода : class Type class Type$1 class Type class Type$2 class Type class Type$3 class Type Таким образом, компилятор создал класс Type и 3 nested класса, производных от Type. Декомпилированный enum-class с наследованиемВ подтверждение вышесказанному можно привести результат декомпиляции перечисления Type из примера выше:
abstract class Type extends Enum {
public static Type[] values() {
return (Type[]) $VALUES.clone();
}
public static Type valueOf(String name) {
return (Type) Enum.valueOf(t / T$Type, name);
}
public boolean isPrimitive() {
return primitive;
}
public abstract Object parse(String s);
public static final Type INT;
public static final Type INTEGER;
public static final Type STRING;
boolean primitive;
private static final Type $VALUES[];
static {
INT = new Type("INT", 0, true) {
public Object parse(String string) { return Integer.valueOf(string); }
};
INTEGER = new Type("INTEGER", 1, false) {
public Object parse(String string) { return Integer.valueOf(string); }
};
STRING = new Type("STRING", 2, false) {
public Object parse(String string) { return string; }
};
$VALUES = (new Type[]{
INT, INTEGER, STRING
});
}
private Type(String s, int i, boolean primitive) {
super(s, i);
this.primitive = primitive;
}
}
Перечисления и параметрический полиморфизмМожет возникнуть вопрос: "А почему вышеуказанное перечисление Type не использует generics" ? Причина кроется в том, что в Java использование generics в enum запрещено. Так следующий пример не будет скомпилирован:
enum Type<T> {}
|
