- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Java: руководство для начинающих (ЛП) - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
TwoGen х = new TwoGen("A", "В");В данном случае в качестве обоих параметров типа Т и V передается один и тот же тип String. Очевидно, что если аргументы типа совпадают, то определять два параметра типа в обобщенном классе нет никакой надобности.### Общая форма обобщенного классаСинтаксис обобщений, представленных в предыдущих примерах, может быть сведен к общей форме. Ниже приведена общая форма объявления обобщенного класса.
class имякласса<списокпараметров_типа> { II ...А вот как выглядит синтаксис объявления ссылки на обобщенный класс:
имякласса<списокаргументовтипа> имяпеременной = new имякласса<списокаргументовтипа> (списокаргументов_конструктора) ;## Ограниченные типыВ предыдущих примерах параметры типа могли заменяться любым типом класса. Такая подстановка оказывается пригодной для многих целей, но иногда бывает полезно ограничить допустимый ряд типов, передаваемых в качестве параметра типа. Допустим, требуется создать обобщенный класс для хранения числовых значений и выполнения над ними различных математических операций, включая получение обратной величины или извлечение дробной части. Допустим также, что в этом классе предполагается выполнение математических операций над данными любых числовых типов: как целочисленных, так и с плавающей точкой. В таком случае будет вполне логично указывать числовой тип данных обобщенно, т.е. с помощью параметра типа. Для создания такого класса можно было бы написать код, аналогичный приведенному ниже.
// Класс NumericFns как пример неудачной попытки создать// обобщенный класс для выполнения различных математических// операций, включая получение обратной величины или// извлечение дробной части числовых значений любого типа,class NumericFns { Т num;// передать конструктору ссылку на числовой объектNumericFns(Т п) { num = п;}// возвратить обратную величинуdouble reciprocal () { return 1 / num.doubleValue(); // Ошибка!}// возвратить дробную частьdouble fraction() { return num.doubleValue() - num.intValue(); // Ошибка!}// ...
}К сожалению, класс NumericFns в таком виде, в каком он приведен выше, не компилируется, так как оба метода, определенные в этом классе, содержат программнуюошибку. Рассмотрим сначала метод reciprocal (), который пытается возвратить величину, обратную его параметру num. Для этого нужно разделить 1 на значение переменной num, которое определяется при вызове метода doubleValue (), возвращающего вариант double числового объекта, хранящегося в переменной num. Как известно, все числовые классы, в том числе Integer и Double, являются подклассами, производными от класса Number, в котором определен метод doubleValue (), что делает его доступным для всех классов оболочек числовых типов. Но дело в том, что компилятору неизвестно, что объекты класса NumericFns предполагается создавать только для числовых типов данных. Поэтому при попытке скомпилировать класс NumericFns возникает ошибка, а соответствующее сообщение уведомляет о том, что метод doubleValue () неизвестен. Аналогичная ошибка возникает дважды при компиляции метода fraction (), где вызываются методы doubleValue () и intValue (). При вызовах обоих этих методов компилятор также сообщает о том, что они неизвестны. Для того чтобы разрешить данное затруднение, нужно каким-то образом сообщить компилятору, что в качестве параметра типа Т предполагается передавать только числовые типы. И нужно еще убедиться, что в действительности передаются только эти типы данныхДля подобных случаев в Java предусмотрены ограниченные типы. При указании параметра типа можно задать верхнюю границу, объявив суперкласс, который должны наследовать все аргументы типа. И делается это с помощью оператора extends, указываемого при определении параметра типа, как показано ниже.
<Т extends суперкласс>В этом объявлении компилятору указывается, что параметр типа Т может быть заменен только суперклассом или его подклассами. Таким образом, суперкласс определяет верхнюю границу в иерархии классов Java.С помощью ограниченных типов можно устранить программные ошибки в классе NumericFns. Для этого следует указать верхнюю границу так, как показано ниже.
//В этой версии класса NumericFns аргументом типа,// заменяющим параметр типа Т, должен стать класс Number// или производный от него подкласс, как показано ниже,class NumericFns { T num;// передать конструктору ссылку на числовой объектNumericFns(Т п) { num = п;}// возвратить обратную величинуdouble reciprocal() { return 1 / num.doubleValue() ;}// возвратить дробную частьdouble fraction() { return num.doubleValue() - num.intValue();}// ...
}
// продемонстрировать класс NumericFnsclass BoundsDemo { public static void main(String args[]) { // Применение класса Integer вполне допустимо, так как он // является подклассом, производным от класса Number. NumericFns<Integer> iOb = new NumericFns<Integer>(5) ; System.out.println("Reciprocal of iOb is " + iOb.reciprocal()); System.out.println("Fractional component of iOb is " + iOb.fraction()); System.out.println(); // Применение класса Double также допустимо. NumericFns<Double> dOb = new NumericFns<Double>(5.25); System.out.println("Reciprocal of dOb is " + dOb.reciprocal()); System.out.println("Fractional component of dOb is " + dOb.fraction()); // Следующая строка кода не будет компилироваться, так как // класс String не является производным от класса Number. // NumericFns<String> strOb = new NumericFns<String>("Error");}
}Ниже приведен результат выполнения данной программы.
Reciprocal of iOb is 0.2Fractional component of iOb is 0.0
Reciprocal of dOb is 0.19047619047619047Fractional component of dOb is 0.25Как видите, для объявления класса NumericFns в данном примере служит следующая строка кода:
class NumericFns {Теперь тип т ограничен классом Number, а следовательно, компилятору Java известно, что для всех объектов типа т доступен метод doubleValue (), а также другие методы, определенные в классе Number. И хотя это само по себе дает немалые преимущества, кроме того, предотвращает создание объектов класса NumericFns для нечисловых типов. Так, если попытаться удалить комментарии из строки кода в конце рассматриваемой здесь программы, а затем повторно скомпилировать ее, то будет получено сообщение об ошибке, поскольку класс String не является подклассом, производным от класса Number.Ограниченные типы оказываются особенно полезными в тех случаях, когда нужно обеспечить совместимость одного параметра типа с другим. Рассмотрим в качестве примера представленный ниже класс Pair. В нем хранятся два объекта, которые должны быть совместимы друг с другом.
// Тип V должен совпадать с типом Т или быть его подклассом.class Pair { Т first; V second;Pair(T a, V b) { first = a; second ='b;}// ...
}В классе Pair определяются два параметра типа т и V, причем V расширяет тип Т. Это означает, что тип V должен быть либо того же типа, что и т, либо его подклассом. Благодаря такому объявлению гарантируется, что два параметра типа, передаваемые конструктору класса Pair, будут совместимы друг с другом. Например, приведенные ниже строки кода составлены правильно.
// Эта строка кода верна, так как Т и V относятся типу Integer.Paircinteger, Integer> х = new Pair(l, 2);
//И эта строка кода верна, так как Integer является подклассом Number.Pair у = new Pair(10.4, 12);А следующий фрагмент кода содержит ошибку:
// Эта строка кода недопустима, так как String не является подклассом Number.Pair z = new Pair(10.4, "12");В данном случае класс String не является производным от класса Number, что нарушает граничное условие, указанное в объявлении класса Pair.## Использование метасимвольных аргументовНесмотря на всю полезность типовой безопасности в обобщениях, иногда она может помешать использованию идеально подходящих языковых конструкций. Допустим, требуется реализовать метод absEqual (), возвращающий логическое значение true в том случае, если два объекта рассмотренного выше класса NumericFns содержат одинаковые абсолютные значения. Допустим также, что этот метод должен оперировать любыми типами числовых данных, которые могут храниться в сравниваемых объектах. Так, если один объект содержит значение 1,25 типа Double, а другой — значение -1,25 типа Float, метод absEqual () должен возвращать логическое значение true. Один из способов реализации метода absEqual () состоит в том, чтобы передавать этому методу параметр типа NumericFns, а затем сравнивать его абсолютное значение с абсолютным значением текущего объекта и возвращать логическое значение true, если эти значения совпадают. Например, вызов метода absEqual () может выглядеть следующим образом:

