Изменения

Перейти к: навигация, поиск

Перечисления

4448 байт добавлено, 15:19, 30 сентября 2013
добавлены EnumMap и EnumSet, изменены и добавлены примеры
== Перечисление - это класс ==
Объявляя enum, мы неявно создаем класс производный от java.lang.Enum. Условно конструкция enum Mark Unit { ... } эквивалентна
class Mark Unit extends java.lang.Enum { ... }.
И хотя явным образом наследоваться от <tex>java.lang.Enum</tex> нам не позволяет компилятор, все же в том, что <tex>enum</tex> наследуется, легко убедиться с помощью <tex>reflection:</tex>
System.out.println(MarkUnit.class.getSuperclass());
На консоль будет выведено:
Начнем с примера. Давайте опишем с помощью enum тип данных для хранения оценки студента:
enum Mark Unit { AKILOMETER, BMETER, C, D, E, F MILLIMETER }
Здесь мы использовали новое ключевое слово enum, присвоили ему имя и указал разрешенные значения. Grade Unit стал перечислимым типом, который вы можете использовать, например, следующим способом:
public class Student Distance { private String Namedouble dist; private Mark markUnit unit; public StudentDistance(String Namedouble dist, Mark markUnit unit) { this.Name unit = Nameunit; this.mark dist = markdist;
}
public void setNamesetUnit(String NameUnit unit) { this.Name unit = Nameunit;
}
public String getNameUnit getUnit() { return Nameunit;
}
public void setMarksetDistance (Mark markdouble dist) { this.mark dist = markdist;
}
public Mark getMarkdouble getDistance() { return markdist;
}
}
Создав новое перечисление (MarkUnit) предварительно определенного типа, вы можете использовать его аналогично любой другой переменной экземпляра. Естественно, перечислению можно присвоить только одно из перечисленных значений (например, A, C, или F). Обратите внимание также на то, что в getMarkgetUnit() нет кода проверки ошибок на выход за пределы границ. ==Добавление методов в enum==У Вас есть возможность добавлять собственные методы как в enum-класс, так и в его элементы: enum Unit { KILOMETER(1e3) METER(1) MILLIMETER(1e-3) private final double length; private Unit(double length) { this.length = length } public double getLength() { return length; } } Обратите внимание что использование конструкторов в enum так же доступно, как и в других классах.  ==Наследование в enum==С помощью enum в Java можно реализовать иерархию классов, объекты которой создаются в единственном экземпляре и доступны статически. При этом элементы enum могут содержать собственные конструкторы.  enum Unit { KILOMETER { public double getLength() { return 1000; } }, METER { public double getLength() { return 1; } }; MILLIMETER { public double getLength() { return 0.001; } }; public abstract double getLength(); } Здесь объявляется перечисление Unit с тремя элементами KILOMETER, METER и MILLIMETER. Компилятор создаст следующие классы и объекты:   •Unit - класс производный от java.lang.Enum •KILOMETER - объект 1-го класса производного от Unit •METER - объект 2-го класса производного от Unit •MILLIMETER - объект 3-го класса производного от Unit Два производных класса будут созданы с полиморфным методом Object parse(String) и конструктором Unit(..., boolean). При этом объекты классов KILLOMETER, MILLIMETER и METER существуют в единственном экземпляре и доступны статически. В этом можно убедится: System.out.println(Unit.class); System.out.println(Unit.KILOMETER.getClass() + " " + Unit.KILOMETER.getClass().getSuperclass()); System.out.println(Unit.METER.getClass() + " " + Unit.METER.getClass().getSuperclass()); System.out.println(Unit.MILLIMETER.getClass() + " " + Unit.MILLIMETER.getClass().getSuperclass());Результат будет следующим: class Unit class Unit $1 class Unit class Unit $2 class Unit class Unit $3 class Unit
==Использование enum==
Рассмотрим пример, показывающий, как пройти по значениям любого перечислимого типа.
public void PrintAllMarksPrintAll (PrintStream out) throws IOException { for (Mark mark Unit u1 : MarkUnit.values()) { for (Unit u2 : Unit.values()) { out.println(String.format("Allowed marks : There are %f %sS in one %s" + mark,u2.getLength()/u1.getLength(), u1, u2)); }
}
}
В результате чего мы получим следующий текст:
Allowed marks : AThere are 1 KILOMETER in one KILIMETER Allowed marks : BThere are 0.001 KILOMETER in one METER Allowed marks : CThere are 0.000001 KILOMETER in one MILLIMETER Allowed marks : DThere are 1000 METER in one KILIMETER Allowed marks : EThere are 1 METER in one METER Allowed marks : FThere are 0.001 METER in one MILLIMETER There are 1000000 MILLIMETER in one KILIMETER There are 1000 MILLIMETER in one METER There are 1 MILLIMETER in one MILLIMETER 
Так же можно использовать следующую запись для вывода значений на экран:
System.out.println(Arrays.toString(MarkUnit.values()));
В результате будет выведено:
[AKILOMETER, BMETER, C, D, E, FMILLIMETER]
===Переключение с enum===
Рассмотренные ранее примеры являются довольно простыми, но перечислимые типы предлагают значительно больше. Перечислимые значения, которые можно использовать для итерации и в операторах <tex>switch</tex>, имеют большое значение.
Для сравнения значения mark unit с разными возможными оценками можно было мерами длин использовать следующую запись:
markunit.equals(MarkUnit.AMETER)
Но множество сравнений заняло бы много места.
Для этого мы используем <tex>switch</tex>, в результате чего у нас получитсяследующая запись:
switch (markunit) { case AKILOMETER: outputText.append(return "Great Mark Akm"); break; case B: // fall through to C case C: outputText.append ("Good Mark ") .append(mark.toString()); break; case D: // fall through to E case EMETER: outputText.append(return "Bad Mark m") .append(student1.getGrade().toString()); break; case FMILLIMETER: outputText.append(return "Negative Mark Fmm"); break;
}
В результате чего он выведет соответствующую оценку. Так же можно употребить <tex>default </tex>, на тот случай, если вдруг другой программист добавил новые значения в MarkUnit, а вас не предупредил. Поставив для варианта <tex>default </tex> вывод сообщения об отсутствии в списке значенияя markunit, вы обнаружите это изменение.
==Получение елемента enum по строковому представлению его имени==
Довольно часто возникает задача получить элемент enum по его строковому представлению. Для этих целей в каждом enum-классе компилятор автоматически создает специальный статический метод: public static EnumClass valueOf(String name), который возвращает элемент перечисления EnumClass с названием, равным name. Пример использования:
String name = "BMETER"; Mark mark Unit unit = MarkUnit.valueOf(name);
В результате чего в mark unit будет записано значение BMETER.
==Добавление методов в enumКоллекции перечислимых типов==У Вас есть возможность добавлять собственные методы как В Java использование генериков в enum-класс, так запрещено. Но можно использовать EnumMap и в его элементы:EnumSet. enum MarkBool { GOOD, BAD; public MarkBool opposite() { return this == GOOD ? BAD : GOOD; }=EnumSet=== }Специализированное Set реализация для использования с перечислимыми типами. Все элементы в перечислимом наборе должны прибыть из единственного перечислимого типа, который определяется, явно или неявно, когда набор создается. Перечислимые наборы представляются внутренне как битовый векторы. Это представление чрезвычайно компактно и эффективно.
==Наследование в enum==С помощью enum в Java можно реализовать иерархию классовНулевые элементы не разрешаются. Попытки вставить нулевой элемент бросят NullPointerException. Попытки протестировать на присутствие нулевого элемента или удалить каждый будет, однако, объекты которой создаются в единственном экземпляре и доступны статически. При этом элементы enum могут содержать собственные конструкторыфункционировать должным образом.
enum MarkBool { GOOD { public MarkBool opposite() { return BAD; } }EnumSet работает почти так же, BAD { public MarkBool opposite() { return GOOD; } }; как и Set. Рассмотрим методы EnumSet :
public abstract MarkBool opposite allOf(Class<E> elementType) - создает перечислимы набор, содержащий все эллементы в указанном типе эллементов.  clone() - Возвращает копию этого набора.  complementOf(EnumSet<E> s) - Создает перечислимый набор с тем же самым типом элемента как указанный перечислимый набор, первоначально содержащий все элементы этого типа, которыене содержатся в указанном наборе.  copyOf(Collection<E> c) - Создает перечислимый набор, инициализированный из указанного набора.  copyOf(EnumSet<E> s) - Создает перечислимый набор с тем же самым типом элемента как указанный перечислимый набор, первоначально содержащий те же самые элементы (если любой).  noneOf(Class<E> elementType) - Создает пустой перечислимый набор с указанным типом элемента.  of(E e1, E e2, E e3...) - Создает перечислимый набор, первоначально содержащий указанные элементы.  range(E from, E to); - Создает перечислимый набор, первоначально содержащий все элементы в диапазоне, }определенном двумя указанными конечными точками. ===EnumMap===EnumMap - это специализированный класс Map, для работы с Enum. В EnumMap все происходит аналогично. Все Эллементы должны быть из единственного перечислимого типа. Эллементы так же хранятся в их естественном порядке(порядок в котором хранятся Enum константы). И Так же не доступен нулевой эллемент, попытки вставить его бросят NullPointerException.  Создание EnumMap :  EnumMap<K,V>(K.class) EnumMap<K,V>(EnumMap<K,V>) EnumMap<K,V>(Map<K,V>)
Здесь объявляется перечисление MarkBool с двумя элементами BAD и GOODМетоды EnumMap соответствуют методам Map. Компилятор создаст следующие классы и объекты: •MarkBool - класс производный от java.lang.Enum •BAD - объект 1-го класса производного от MarkBool •GOOD - объект 2-го класса производного от MarkBoolДва производных класса будут созданы с полиморфным методом Object parse(String) и конструктором MarkBool(..., boolean) При этом объекты классов BAD и GOOD существуют в единственном экземпляре и доступны статически. В этом можно убедится: System.out.println(MarkBool.class); System.out.println(MarkBool.BAD.getClass() + " " + MarkBool.BAD.getClass().getSuperclass()); System.out.println(MarkBool.GOOD.getClass() + " " + MarkBool.GOOD.getClass().getSuperclass());Результат будет следующим: class MarkBool class MarkBool $1 class MarkBool class MarkBool $2 class MarkBool
==Пример==
9
правок

Навигация