- •Глава 2 3
- •Глава 3 11
- •Глава 10 117
- •Глава 2 Автоупаковка и автораспаковка
- •Обзор оболочек типов и упаковки значений
- •Основы автоупаковки/распаковки
- •Автоупаковка и методы
- •Автоупаковка/распаковка в выражениях
- •Автоупаковка/распаковка логических и символьных значений
- •Помощь автоупаковки/распаковки в предупреждении ошибок
- •Предостережения
- •Глава 3 Настраиваемые типы
- •Что такое настраиваемые типы
- •Простой пример применения настраиваемых типов
- •Средства настройки типов работают только с объектами
- •Различия настраиваемых типов, основанных на разных аргументах типа
- •Как настраиваемые типы улучшают типовую безопасность
- •Настраиваемый класс с двумя параметрами типа
- •Общий вид объявления настраиваемого класса
- •Ограниченные типы
- •Применение метасимвольных аргументов
- •Ограниченные метасимвольные аргументы
- •Создание настраиваемого метода
- •Настраиваемые конструкторы
- •Настраиваемые интерфейсы
- •Типы raw и разработанный ранее код
- •Иерархии настраиваемых классов
- •Использование настраиваемого суперкласса
- •Настраиваемый подкласс
- •Сравнения типов настраиваемой иерархии во время выполнения программы
- •Переопределенные методы в настраиваемом классе
- •Настраиваемые типы и коллекции
- •Стирание
- •Методы-подставки
- •Ошибки неоднозначности
- •Некоторые ограничения применения настраиваемых типов
- •Нельзя создавать объекты, используя параметры типа
- •Ограничения для статических членов класса
- •Ограничения для настраиваемого массива
- •Ограничение настраиваемых исключений
- •Заключительные замечания
- •Глава 4 Вариант For-Each цикла for
- •Описание цикла for-each
- •Обработка многомерных массивов в цикле
- •Область применения цикла for в стиле for-each
- •Использование цикла for в стиле for-each для обработки коллекций
- •Создание объектов, реализующих интерфейс Iterable
- •Глава 5 Аргументы переменной длины
- •Средство формирования списка с переменным числом аргументов
- •Перегрузка методов с аргументом переменной длины
- •Аргументы переменной длины и неоднозначность
- •Глава 6 Перечислимые типы
- •Описание перечислимого типа
- •Методы values() и valueOf()
- •Перечислимый тип в Java — это класс
- •Перечислимые типы, наследующие тип enum
- •Глава 7 Метаданные
- •Описание средства "метаданные"
- •Задание правил сохранения
- •Получение аннотаций во время выполнения программы с помощью рефлексии
- •Листинг 7.3. Получение всех аннотаций для класса и метода
- •Интерфейс AnnotatedElement
- •Использование значений по умолчанию
- •Аннотации-маркеры
- •Одночленные аннотации
- •Встроенные аннотации
- •Несколько ограничений
- •Глава 8 Статический импорт
- •Описание статического импорта
- •Общий вид оператора статического импорта
- •Импорт статических членов классов, созданных Вами
- •Неоднозначность
- •Предупреждение
- •Глава 9 Форматированный ввод/вывод
- •Форматирование вывода с помощью класса Formatter
- •Конструкторы класса Formatter
- •Методы класса Formatter
- •Основы форматирования
- •Форматирование строк и символов
- •Форматирование чисел
- •Форматирование времени и даты
- •Спецификаторы %n и %%
- •Задание минимальной ширины поля
- •Задание точности представления
- •Применение флагов форматирования
- •Выравнивание вывода
- •Флаг запятая
- •Применение верхнего регистра
- •Использование порядкового номера аргумента
- •Применение метода printf() языка Java
- •Класс Scanner
- •Конструкторы класса Scanner
- •Описание форматирования входных данных
- •Несколько примеров применения класса Scanner
- •Установка разделителей
- •Другие свойства класса Scanner
- •Глава 10 Изменения в api
- •Возможность применения настраиваемых типов при работе с коллекциями
- •Обновление класса Collections
- •Почему настраиваемые коллекции
- •Модернизация других классов и интерфейсов для применения настраиваемых типов
- •Новые классы и интерфейсы, добавленные в пакет java.Lang
- •Класс ProcessBulider
- •Класс StringBuilder
- •Интерфейс Appendable
- •Интерфейс Iterable
- •Интерфейс Readable
- •Новые методы побитной обработки классов Integer и Long
- •Методы signum() u reverseBytes()
- •Поддержка 32-битных кодовых точек для символов Unicode
- •Новые подпакеты пакета java.Lang
- •Классы Formatter и Scanner
Создание настраиваемого метода
Как показано в предыдущих примерах, методы в настраиваемых классах могут использовать параметр типа и таким образом автоматически становятся настраиваемыми по отношению к этому параметру типа. Однако можно и объявить настраиваемый метод (generic method) с одним или несколькими собственными параметрами типа. Более того, есть возможность создать настраиваемый метол внутри ненастраиваемого класса.
Начнем с примера. В программе из листинга 3.8 объявляется ненастраивае-мый класс, названный GenMethDemo, и внутри класса статический настраиваемый метод с именем isIn (). Метод isIn ( ) определяет, является ли объект элементом массива. Он может использоваться с объектом любого типа и любым массивом, при условии, что массив содержит объекты, тип которых сопоставим с типом проверяемого объекта.
Листинг 3.8. Демонстрация простого настраиваемого метода
class GenMethDemo {
// Определяет, является ли объект элементом массива.
static <T, V extends T> boolean isIn(T x, V[] y) {
for(int i=0; i < y.length; i++)
if(x.equals(y[i])) return true;
return false;
}
public static void main(String args[]) {
// Использует метод isin() для объектов типа Integer.
Integer nums[] = { 1, 2, 3, 4, 5 };
if(isIn(2, nums))
System.out.println("2 is in nums");
if(!isIn(7, nums))
System.out.println("7 is not in nums");
System.out.println();
// Использует метод isIn() для объектов типа String.
String strs[] = { "one", "two", "three",
"four", "five" };
if(isIn("two", strs))
System.out.println("two is in strs");
if(!isIn("seven", strs))
System.out.println("seven is not in strs");
// Opps! He откомпилирует, поскольку типы не совместимы.
// if(isln("two", nums})
// System.out.println("two is in strs”);
}
}
Далее приведен вывод результатов работы программы из листинга 3.8:
2 is in nums
7 is not in nums
two is in strs
seven is not in strs
Рассмотрим подробно метод isIn(). Во-первых, обратите внимание на его объявление, приведенное в следующей строке:
static <T, V extends T> boolean isIn(T х, V[] у) {
Параметры типа указаны перед типом значения, возвращаемого методом. Во-вторых, обратите внимание на то, что параметр типа v ограничен сверху параметром типа т. Следовательно, тип параметра v должен быть таким же, как у параметра T или классом, производным от T. Описанная взаимосвязь параметров обеспечивает вызов метода isIn( ) с аргументами, сопоставимыми друг с другом. Отметьте также то, что метод isIn( ) статический, т. е. может вызываться независимо от какого-либо объекта. Однако настраиваемые методы могут быть как статическими, так и нестатическими, на этот счет нет никаких ограничений.
Теперь рассмотрим как метод isIn () вызывается в методе main ( ) с использованием обычного синтаксиса вызова без необходимости указания аргументов типа. Это возможно благодаря тому, что типы аргументов распознаются автоматически и типы Т и V настраиваются соответственно. Например, в первом вызове:
if(isIn(2, nums))
тип первого аргумента — Integer (в результате автоупаковки), что вызывает замену типа T классом Integer, Базовый тип второго аргумента тоже Integer, что в свою очередь ведет к замене параметра V классом Integer.
Во втором вызове используется тип String, и параметры T и V заменяются классом String.
Теперь рассмотрим строки комментария приведенные далее:
// if(isIn("two", nums))
// System.out.println("two is in strs");
Если Вы удалите знаки комментария и попробуете откомпилировать программу, то получите сообщение об ошибке. Причина заключается в том, что параметр типа v ограничен типом T с помощью ключевого слова extends при объявлении параметра V. Это означает, что тип параметра V должен быть таким же, как тип параметра T или классом, производным от типа T. В нашем случае у первого аргумента тип — String, заменяющий T классом String, а у второго аргумента тип Integer который не является подклассом типа String. Подобная ситуация приводит к появлению ошибки несовместимости типов на этапе компиляции. Описанная способность обеспечения типовой безопасности — одно из важнейших преимуществ настраиваемых методов.
Далее приведена синтаксическая запись для настраиваемого метода:
<type-param-list> ret-type meth-name(param-list) { //...
type-param-list всегда представляет собой разделенный запятыми список параметров типа. Обратите внимание на то, что у настраиваемых методов этот список предшествует типу значения, возвращаемого методом.
