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

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

Что такое упаковка и распаковка? В каких случаях производится автоупаковка и автораспаковка?

Измените следующий фрагмент кода таким образом, чтобы в нем производилась автоупаковка: Short val = new Short (123);

Объясните, что такое статический импорт?

Какие действия выполняет приведенный ниже оператор? import static java.lang.Integer.parselnt;

Следует ли употреблять статический импорт от случая к случаю или желательно импортировать статические члены всех классов?

Синтаксис аннотации основывается на .

Какая аннотация называется маркером?

Аннотации применимы только к методам. Верно или неверно?

Глава 13 Обобщения

Основные навыки и понятия

Преимущества обобщений

Создание обобщенного класса

Применение ограниченных параметров типов

Использование метасимвольных аргументов

Применение ограниченных метасимвольных аргументов

Создание обобщенного метода

Создание обобщенного конструктора

Создание обобщенного интерфейса



Использование базовых типов

Выводимость типов с помощью ромбовидного оператора

Стирание

Исключение ошибок неоднозначности

Наложение ограничений на обобщения

Начиная с версии 1.0 в Java было реализовано много новых языковых средств. Все они очень полезны и расширяют область применения Java, но на одном из них следует остановиться особо, поскольку оно оказывает огромное влияние на язык в целом. Речь идет об обобщениях — совершенно новой синтаксической конструкции, появление которой вызвало существенные изменения во многих классах и методах базового интерфейса API. Не будет преувеличением сказать, что введение обобщений коренным образом изменило сам язык Java.

Обобщения — слишком обширная тема, чтобы подробно рассматривать ее в этой книге. Тем не менее всякий программирующий на Java должен иметь хотя бы общее представление об этом языковом средстве. На первый взгляд синтаксис обобщений может показаться непонятным, но на самом деле пользоваться ими совсем не трудно. К тому моменту, когда вы завершите проработку материала этой главы, вы не только усвоите основы обобщений, но и научитесь успешно применять их в своих программах.Основные положения об обобщениях

Термин обобщение, по существу, означает параметризированный тип. Особая роль параметризированных типов состоит в том, что они позволяют создавать классы, интерфейсы и методы, в которых обрабатываемые данные указываются в виде параметра. С помощью обобщений можно, например, создать единый класс, который автоматически становится пригодным для обработки разнотипных данных. Класс, интерфейс или метод, оперирующий параметризированным типом данных, называется обобщенным, как, например, обобщенный класс или обобщенный метод.

Главное преимущество обобщенного кода состоит в том, что он автоматически настраивается на работу с нужным типом данных. Многие алгоритмы выполняются одинаково, независимо от того, к данным какого типа они должны применяться. Например, быстрая сортировка не зависит от типа данных, в качестве которого можно использовать Integer, String, Object и даже Thread. Используя обобщения, можно реализовать алгоритм один раз, а затем применять его без особого труда к любому типу данных.

Следует особо подчеркнуть, что в Java всегда имелась возможность создавать обобщенный код, оперируя ссылками типа Object. А поскольку класс Object является суперклассом для всех остальных классов, то по ссылке типа Object можно обращаться к объекту любого типа. Таким образом, до появления обобщений для оперирования разнотипными объектами в программах служил обобщенный код, в котором для этой цели использовались ссылки типа Object.

Но дело в том, что в таком коде трудно было соблюсти типовую безопасность, поскольку для преобразования типа Object в конкретный тип данных требовалось приведение типов. А это служило потенциальным источником ошибок из-за того, что приведение типов могло быть неумышленно выполнено неверно. Это затруднение позволяют преодолеть обобщения, обеспечивая типовую безопасность, которой раньше так недоставало. Кроме того, обобщения упрощают весь процесс, поскольку исключают необходимость выполнять приведение типов для преобразования объекта или другого типа обрабатываемых данных. Таким образом, обобщения расширяют возможности повторного использования кода и позволяют делать это надежно и просто.Простой пример обобщений

Прежде чем приступать к более подробному рассмотрению обобщений, полезно рассмотреть простой пример их применения. Ниже приведен исходный код программы, в которой объявлены два класса. Первым из них является обобщенный класс Gen, вторым — класс GenDemo, в котором используется класс Gen.// Простой обобщенный класс.// Здесь Т - это параметр типа, заменяемый именем// подлинного типа при создании объекта класса Gen.//В объявлении этого класса Т означает обобщенный тип.class Gen<T> { Т ob; // объявить объект типа Т // передать конструктору ссылку на объект типа Т. Gen (Т о) { ob = о; } // возвратить объект ob из метода Т getob() { return ob; } // отобразить тип Т void showTypeO { System.out.println("Type of T is " + ob.getClass().getName()); }}// продемонстрировать обобщенный классclass GenDemo { public static void main(String args[]) { // Создание ссылки на объект типа Gen<Integer>. Gen<Integer> iOb; // Создать объект типа Gen<Integer> и присвоить ссылку на // него переменной iOb. Обратите внимание на автоупаковку при // инкапсуляции значения 88 в объекте типа Integer. iOb = new Gen<Integer>(88); // получить экземпляр типа Gen<Integer> // отобразить тип данных, используемых в объекте iOb iOb.showType(); // Получение значения из объекта iOb. Обратите внимание // на то,что приведение типов здесь не требуется, int v = iOb.getob(); System.out.println("value: " + v); System.out.println(); // Создание объекта типа Gen для символьных строк. // Здесь создается ссылка и сам объект типа Gen<String>. Gen<String> strOb = new Gen<String>("Generics Test"); // отобразить тип данных, используемых в объекте strOb strOb.showType(); // Получение значения из объекта strOb. //И здесь приведение типов не требуется. String str = strOb.getob(); System.out.println("value: " + str) ; }}

Выполнение данной программы дает следующий результат:Type of Т is java.lang.Integervalue: 88Type of Т is java.lang.Stringvalue: Generics Test

Рассмотрим исходный код данной программы более подробно. Прежде всего обратите внимание на то, как объявляется класс Gen. Для этого используется следующая строка кода:class Gen<T> {``где Т — имя параметра типа. Это имя служит в качестве метки-заполнителя конкретного типа, который указывается при создании объекта класса Gen. Следовательно, имя т используется в классе Gen всякий раз, когда требуется параметр типа. Обратите внимание на то, что имя т заключается в угловые скобки (< >). Этот синтаксис можно обобщить: всякий раз, когда объявляется параметр типа, он указывается в угловых скобках. А поскольку параметр типа используется в классе Gen, то такой класс считается обобщенным.В объявлении класса Gen можно указывать любое имя параметра типа, но по традиции выбирается имя Т. К числу других наиболее употребительных имен параметров типа относятся V и Е. А вообще, обозначать параметры типа рекомендуется одной прописной буквой.Далее имя т используется для объявления объекта ob, как показано в следующей строке кода:

Т ob; // объявить объект типа ТКак пояснялось выше, имя параметра типа т служит меткой-заполнителем конкретного типа, указываемого при создании объекта класса Gen. Поэтому объект ob будет иметь тип, передаваемый в качестве параметра типа т при получении экземпляра объекта класса Gen. Так, если качестве параметра типа Т указывается String, то экземпляр объекта оЪ будет отнесен к типу String.Рассмотрим далее конструктор класса Gen.

Gen(Т о) { ob = о;}Как видите, параметр о этого конструктора относится к типу Т. Это означает, что конкретный тип параметра о определяется типом, передаваемым в качестве параметра типа Т при создании объекта класса Gen. А поскольку параметр о и переменная экземпляра ob относятся к типу Т, то после создания объекта класса Gen их конкретный тип окажется одним и тем же.С помощью параметра типа т можно также указывать тип, возвращаемый методом, как показано ниже на примере метода getob ().