410013796724260
• Webmoney
R335386147728
Z369087728698
Перечисления 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> {}
|
