Опубликован: 04.12.2009 | Доступ: свободный | Студентов: 8424 / 660 | Оценка: 4.30 / 3.87 | Длительность: 27:27:00
Лекция 7:

Важнейшие объектные типы

7.7. Типы-перечисления (enum)

Иногда требуется использовать элементы, которые не являются ни числами, ни строками, но ведут себя как имена элементов и одновременно обладают порядковыми номерами. Например, названия месяцев или дней недели. В этих случаях используют перечисления. Для задания типа какого-либо перечисления следует написать зарезервированное слово enum (сокращение от enumeration – "перечисление"), после которого имя задаваемого типа, а затем в фигурных скобках через запятую элементы перечисления. В качестве элементов можно использовать любые простые идентификаторы (не содержащие квалификаторов вида имя1.имя2 ).

Тип-перечисление обязан быть глобальным – он может задаваться либо на уровне пакета, либо в каком-либо классе. Но его нельзя задавать внутри какого-либо метода. Элементы перечисления могут иметь любые имена, в том числе совпадающие в разных перечислениях или совпадающие с именами классов или их членов – каждое перечисление имеет свое собственное пространство имен. Доступ к элементу перечисления осуществляется с квалификацией именем типа-перечисления:

  • ИмяТипа.имяЭлемента

У каждого элемента перечисления имеется порядковый номер, соответствующий его положению в наборе - нумерация начинается с нуля. Поэтому первый элемент имеет номер 0, второй элемент – номер 1, и так далее. Имеется функция ordinal(), возвращающая порядковый номер элемета в перечислении. Также имеется функция compareTo, позволяющая сравнивать два элемента перечисления - она возвращает разницу в их порядковых номерах.

Строковое представление значения можно получить с помощью функции name(). Преобразование из строки в значение типа "перечисление" осуществляется с помощью функции класса valueOf, в которую передается строковое представление значения.

Если требуется рассматривать элементы перечисления как массив, можно воспользоваться функцией values() – она возвращает массив элементов, к которым можно обращаться по индексу. Формат вызова функции такой: ИмяТипа.values()

Для примера зададим типы-перечисления Monthes ("месяцы") и Spring ("весна"), соответствующие различным наборам месяцев:

enum Monthes {jan,feb,mar,apr,may,jun,jul,aug,sept,oct,nov,dec};
enum Spring { march, apr, may };

Названия месяцев мы намеренно пишем со строчной буквы для того, чтобы было понятно, что это идентификаторы переменных, а не типы. А имя марта написано по-разному в типах Monthes и Spring для того, чтобы показать независимость их пространств имен. Объявление переменных типа "перечисление" делается так же, как для всех остальных типов, при этом переменные могут быть как неинициализированы, так и инициализированы при задании:

  • public Monthes m1 ,m2=Monthes.mar, m3; - при задании в классе общедоступных полей m1, m2 и m3,
  • Spring spr1=Spring.apr, spr2; - при задании в методе локальной переменной или задании в классе поля spr1 с пакетным уровнем доступа.

После чего возможны следующие операторы:

spr2=spr1;
spr1=Spring.may;
System.out.println("Результат сравнения="+spr2.compareTo(Spring.march));

После выполнения этих операторов в консольное окно будет выведен текст

Результат сравнения=1 ,

поскольку в переменной spr2 окажется значение Spring.apr, порядковый номер которого на 1 больше, чем у значения Spring.march, с которым идет сравнение.

Пусть в переменной spr2 хранится значение Spring.may. Порядковый номер значения, хранящегося в переменной, можно получить с помощью вызова spr2.ordinal(). Он возвратит число 2, так как may – третий элемент перечисления (сдвиг на 1 получается из-за того, что нумерация начинается с нуля).

Строковое представление значения, хранящегося в переменной spr2, можно получить с помощью вызова spr2.name(). Он возвратит строку "may" - имя типа в возвращаемое значение не входит.

Если переменная типа "перечисление" не инициализирована, в ней хранится значение null. Поэтому вызов

System.out.println("spr2="+spr2);

осуществленный до присваивания переменной spr2 значения возвратит строку

spr2=null

А вот попытки вызовов spr2.ordinal() или spr2.name() приведут к возникновению ошибки (исключительной ситуации) с диагностикой

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException

Получение значения типа Spring по номеру, хранящемуся в переменной i, осуществляется так:

spr1=Spring.values()[i];

Преобразование из строки в значение типа Spring будет выглядеть так:

spr1=Spring.valueOf("march");

Краткие итоги

  • В Java массивы являются объектами, но особого рода – их объявление отличается от объявления других видов объектов. Переменная типа массив является ссылочной. Массивы Java являются динамическими - в любой момент им можно задать новую длину.
  • Двумерный массив представляет собой массив ячеек, каждая из которых имеет тип "одномерный массив". Трехмерный – массив двумерных массивов. Соответствующим образом они и задаются.
  • Для копирования массивов лучше использовать метод System.arraycopy. Быстрое заполнение массива одинаковыми значениями может осуществляться методом Arrays.fill - класс Arrays расположен в пакете java.util Поэлементное сравнение массивов следует выполнять с помощью метода Arrays.equals (сравнение на равенство содержимого массивов) либо Arrays.deepEquals (глубокое сравнение, то есть на равенство содержимого, а не ссылок – на произвольном уровне вложенности). Сортировка (упорядочение по значениям) массива производится методом Arrays.sort.
  • Коллекции (Collections) – "умные" массивы с динамически изменяемой длиной, поддерживающие ряд важных дополнительных операций по сравнению с массивами. Доступ к элементам коллекции в общем случае не может осуществляться по индексу, так как не все коллекции поддерживают индексацию элементов. Эту функцию осуществляют с помощью специального объекта – итератора (iterator). У каждой коллекции имеется свой итератор который умеет с ней работать.
  • Класс String инкапсулирует действия со строками. Объект типа String – строка, состоящая из произвольного числа символов, от 0 до 2*10^9. Литерные константы типа String представляют собой последовательности символов, заключенные в двойные кавычки. В классе Object имеется метод toString(), обеспечивающий строковое представление любого объекта.
  • Строки типа String являются неизменяемыми объектами – при каждом изменении содержимого строки создается новый объект-строка. Для того чтобы сделать работу с многочисленными присваиваниями более эффективной, используются классы StringBuffer и StringBuilder.
  • Вывод графики осуществляется с помощью методов объекта типа java.awt.Graphics. Для того, чтобы результаты вывода не пропадали, в классе приложения требуется переопределить метод paint, вызываемый при отрисовке. А также обработчик события ComponentResized.
  • Исключительные ситуации в Java являются объектами. Их типы являются классами-потомками объектного типа Throwable. От Throwable наследуются классы Error ("Ошибка") и Exception ("Исключение"). Экземплярами класса Error являются непроверяемые исключительные ситуации, которые невозможно перехватить в блоках catch. Экземплярами класса Exception и его потомков являются проверяемые исключительные ситуации. Кроме одного потомка – класса RuntimeException (и его потомков).
  • Непроверяемые исключения генерируются и обрабатываются системой автоматически – как правило, приводя к завершению приложения. При этом их типы нигде не указываются, и слово throws в заголовке метода указывать не надо. Если же в теле реализуемого метода используется вызов метода, который может возбуждать исключительную ситуацию, и это исключение не перехватывается, в заголовке реализуемого метода требуется указывать соответствующий тип возбуждаемого исключения.
  • Объекты типа File обеспечивают работу с именами файлов и папок (проверка существования файла или папки с заданным именем, нахождение абсолютного пути по относительному и наоборот, проверка и установка атрибутов файлов и папок).
  • При работе с файлами в подавляющем большинстве приложений требуется вызов файлового диалога JFileChooser (пакет javax.swing).
  • Потоки ввода-вывода обеспечивают работу не только с файлами, но и с памятью, а также различными устройствами ввода-вывода. Соответствующие классы расположены в пакете java.io. Абстрактный класс InputStream ("входной поток") инкапсулирует модель входных потоков, позволяющих считывать из них данные. Абстрактный класс OutputStream ("выходной поток") - модель выходных потоков, позволяющих записывать в них данные.
  • Для чтения строк (в виде массива символов) используются потомки абстрактного класса Reader ("читатель"). В частности, для чтения из файла – класс FileReader. Аналогично, для записи строк используются классы- потомки абстрактного класса Writer ("писатель"). В частности, для записи массива символов в файл – класс FileWriter.
  • Имеется еще один важный класс для работы с файлами - RandomAccessFile ("файл с произвольным доступом"), предназначенный для чтения и записи данных в произвольном месте файла. Такой файл с точки зрения класса RandomAccessFile представляет массив байт, сохраненных на внешнем носителе. Класс RandomAccessFile не является абстрактным, поэтому можно создавать его экземпляры.

Задания

  • Написать пример с графическим пользовательским интерфейсом для записи численных данных в файл и считывания их из файла с помощью классов FileInputStream/FileOutputStream (потомков InputStream/OutputStream ). Использовать диалоги выбора файлов.
  • Написать пример с графическим пользовательским интерфейсом для записи численных данных в файл и считывания их из файла с помощью класса RandomAccessFile. Использовать диалоги выбора файлов.
  • Написать пример с графическим пользовательским интерфейсом для записи строковых данных в файл из компонента JTextArea и считывания их из файла с помощью класса RandomAccessFile. Использовать диалоги выбора файлов. Проверить работу с русским языком при записи и чтении текста в различных кодировках (ANSI, UNICODE,UTF-8).
  • Написать пример сложения, вычитания, умножения матриц задаваемых пользователем размеров. Для визуального представления матриц использовать компоненты JTable. Действия проводить с помощью массивов чисел типа double.
  • Усложнить пример, добавив возможность сохранения каждой из трех матриц в текстовый файл, и загрузки первых двух матриц из текстового файла.
Полетаев Дмитрий
Полетаев Дмитрий
Не очень понятно про оболочечные Данные,ячейки памяти могут наверно размер менять,какое это значение те же операции только ячейки больше,по скорости тоже самое
Максим Старостин
Максим Старостин

Код с перемещением фигур не стирает старую фигуру, а просто рисует новую в новом месте. Точку, круг.