Добавить в цитаты Настройки чтения

Страница 92 из 133

В предыдущем примере использовался только один конструктор, но перечисления, как и обычные классы, допускают любое число конструкторов.Два важных ограничения

На перечисления накладываются два ограничения. Во-первых, перечисление не может быть подклассом другого класса. И во-вторых, перечисление не может выступать в роли суперкласса. Иными словами, перечислимый тип enum нельзя расширять. Если бы это было не так, перечисления действовали бы как обычные классы. Основной же особенностью перечислений является создание констант в виде объектов того класса, в котором они были объявлены.Наследование перечислений от класса Enum

Несмотря на то что при объявлении перечислимого типа enum нельзя указывать суперкласс, все перечисления автоматически наследуют переменные и методы от класса java.lang.Enum. В этом классе определен ряд методов, доступных для использования всеми перечислениями. И хотя большинство этих методов используются редко, тем не менее два из них иногда применяются в программах на Java. Это методы ordinal () и compareTo().

Метод ordinal () принимает значение, обозначающее положение константы перечислимого типа в списке. Это значение принято называть порядковым. Ниже приведена общая форма объявления метода ordinal ().final int ordinal()

Этот метод возвращает порядковое значение вызывающей константы. Отсчет порядковых значений начинается с нуля. Следовательно, в упоминавшемся выше перечислении Transport порядковое значение константы CAR равно нулю, константы TRUCK — 1, константы AIRPLANE — 2 И Т.Д.

Для сравнения порядковых значений двух констант в одном и том же перечислении можно воспользоваться методом compareTo (). Ниже приведена общая форма объявления этого метода.final int compareTo(перечислимый_тип е)

Здесь в качестве параметра е задается константа, сравниваемая с вызывающей константой, а перед ней указывается перечислимый_тип, к которому эта константа относится. Следует иметь в виду, что вызывающая константа и константа е должны относиться к одному и тому же перечислимому типу. Так, если порядковое значение вызывающей константы оказывается меньше, чем у константы е, метод compareTo () возвращает отрицательное значение. Если же их порядковые значения совпадают, вращается нулевое значение. И наконец, если порядковое значение вызывающей константы больше, чем у константы е, метод возвращает положительное значение.

Ниже приведен пример программы, демонстрирующий применение методов ordinal() иcompareTo().// Применение методов ordinal() и compareTo().// Перечисление разных видов транспорта,enum Transport { CAR, TRUCK, AIRPLANE, TRAIN, BOAT}class EnumDemo4 { public static void main(String args[]) { Transport tp, tp2, tp3; // получить все порядковые значения с помощью метода ordinal() System.out.println("Here are all Transport constants" + " and their ordinal values: "); for(Transport t : Transport.values()) // Получение порядковых значений констант. System.out.println(t + " " + t.ordinal()); tp = Transport.AIRPLANE; tp2 = Transport.TRAIN; tp3 = Transport.AIRPLANE; System.out.println(); // продемонстрировать применение метода сошрагеТо() // Сравнение порядковых значений констант. if(tp.compareTo(tp2) < 0) System.out.println(tp + " comes before " + tp2) ; if(tp.compareTo(tp2) > 0) System.out.println(tp2 + " comes before " + tp); if(tp.compareTo(tp3) == 0) System.out.println(tp + " equals " + tp3); }}

Результат выполнения данной программы выглядит следующим образом:Here are all Transport constants and their ordinal values:CAR 0TRUCK 1AIRPLANE 2TRAIN 3BOAT 4AIRPLANE comes before TRAINAIRPLANE equals AIRPLANE

Пример для опробования 12.1.Автоматизированный светофор

Перечисления оказываются полезными в тех случаях, когда в программе требуется набор констант, конкретные значения которых не важны, — достаточно, чтобы они отличались друг от друга. Необходимость в подобных наборах констант часто возникает при написании программ. Одним из характерных тому примеров служит поддержка устройств, которые могут находиться в нескольких фиксированных состояниях.Допустим, требуется программа, управляющая светофором, переключающимся в три состояния, обозначаемые зеленым, желтым и красным цветом. Необходимо также, чтобы программа могла определять текущий цвет и устанавливать светофор в исходное состояние. Таким образом, нужно как-либо представлять три возможных состояния светофора. И хотя для этой цели вполне допустимо применять целочисленные значения, например, 1, 2 и 3 или символьные строки "red" (красный), "green" (зеленый) и "yellow" (желтый), вместо них лучше всего воспользоваться перечислением. С помощью перечисления можно написать более эффективный и структурированный код, чем тот, в котором применяются символьные строки и целочисленные значения.



В этом проекте предстоит сымитировать автоматизированный светофор. А по ходу дела будет продемонстрировано применение не только перечислений, но и многопоточной обработки и синхронизации потоков.

Последовательность действий

Создайте файл TrafficLightDemo.java.

Начните с создания перечисления TrafficLightColor, которое представляет три состояния светофора. // Перечисление, представляющее состояния светофора, enum TrafficLightColor { RED, GREEN, YELLOW } Каждая из констант в этом перечислении соответствует одному цвету светофора.

Далее начните определение класса Traf f icLightSimulator так, как показано ниже. Этот класс инкапсулирует имитацию светофора. // Имитация автоматизированного светофора, class TrafficLightSimulator implements Ru

Как видите, класс TrafficLightSimulator реализует интерфейс Ru

А теперь рассмотрим переменные экземпляра. Ссылка на поток, регулирующий состояние и цвет светофора, хранится в переменной thrd. А сведения о текущем цвете хранятся в переменной tic. Переменная stop служит для остановки имитации автоматизированного светофора. Первоначально она принимает логическое значение false. Имитация светофора будет действовать до тех пор, пока эта переменная не примет логическое значение true. И наконец, переменная changed принимает логическое значение true при переключении светофора, когда его цвет меняется.

Введите приведенный ниже метод run (), начинающий имитацию автоматизированного светофора. // Запуск имитации автоматизированного светофора, public void run () { while(!stop) { try { switch(tic) { case GREEN: Thread.sleep(10000); // Зеленый на 10 секунд break; case YELLOW: Thread.sleep(2000); // Желтый на 2 секунды break; case RED: Thread.sleep(12000); // Красный на 12 секунд break; } } catch(InterruptedException exc) { System.out.println(exc); } changeColor(); } }

Этот метод переключает цвета светофора по очереди. Сначала выполнение потока приостанавливается на заданный промежуток времени, который выбирается в зависимости от конкретного цвета светофора. Затем вызывается метод changeColor (), переключающий цвет светофора.

Введите приведенный ниже метод changeColor (), переключающий цвет светофора. // Переключение цвета светофора, synchronized void changeColor() { switch(tic) { case RED: tic = TrafficLightColor.GREEN; break; case YELLOW: tic = TrafficLightColor.RED; break; case GREEN: tic = TrafficLightColor.YELLOW; } changed = true; notify(); // уведомить о переключении цвета светофора }