Выбрать главу

// Экземпляр типа Т получить нельзя, class Gen { Т ob; Gen () { ob = new T(); // Недопустимо!!! } } В данном примере любая попытка получить экземпляр типа т приводит к ошибке. Ее причину понять нетрудно: компилятору ничего не известно о типе создаваемого объекта, поскольку тип Т является заполнителем, который стирается во время компиляции. ### Ограничения, накладываемые на статические члены класса В статических членах нельзя использовать параметры типа, объявленные в содержащем их классе. Так, все объявления статических членов в приведенном ниже классе недопустимы.

class Wrong { // Статическую переменную типа Т создать нельзя, static Т ob; // В статическом методе нельзя использовать тип Т. static Т getob() { return ob; } // Статический метод не может обращаться к объекту типа Т. static void showob() { System.out.println(ob); }

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

// Обобщенные типы и массивы, class Gen { T ob; T vals[]; // Допустимо. Gen(T о, T[] nums) { ob = о; // Следующее выражение недопустимо: // vals = new Т[10]; // Нельзя создать массив типа Т. // Следующее выражение составлено верно. vals = nums; // Переменной допускается присваивать ссылку // на существующий массив. }

}

class GenArrays { public static void main(String args[]) { Integer n[] = { 1, 2, 3, 4, 5 }; Gen<Integer> iOb = new Gen<Integer>(50, n); // Нельзя создать массив обобщенных ссылок // на объекты конкретного типа. // Gen<Integer> gens[] = new Gen<Integer>[10]; // Ошибка! // Следующее выражение составлено верно. Gen<?> gens[] = new Gen<?>[10]; }

} Как следует из исходного кода приведенной выше программы, допускается создавать ссылку на массив типа т. Это демонстрируется в следующей строке кода:

Т vals[]; // Допустимо. Но получить экземпляр самого массива типа т нельзя. Именно поэтому приведенная ниже строка кода закомментирована.

// vals = new Т[10]; // Нельзя создать массив типа Т. В данном случае ограничение на массив типа т состоит в том, что компилятору не известно, какого типа массив следует создавать на самом деле. Но в то же время конструктору Gen () можно передать ссылку на массив совместимого типа при создании объекта, а также присвоить это значение переменной vals. Примером тому может служить следующая строка кода:

vals = nums; // Переменной допускается присваивать ссылку // на существующий массив. Это выражение составлено верно, поскольку тип массива, передаваемого конструктору Gen () при создании объекта, известен и совпадает с типом Т. В теле метода main () содержится выражение, демонстрирующее невозможность объявить массив обобщенных ссылок на объекты конкретного типа. Поэтому приведенная ниже строка кода не будет скомпилирована.

// Gen gens[] = new Gen[10] ; // Ошибка! ### Ограничения, накладываемые на обобщенные исключения Обобщенный класс не может расширять класс Throwable. Это означает, что создавать обобщенные классы исключений нельзя. ### Дальнейшее изучение обобщений Как пояснялось в начале этой главы, приведенных в ней сведений достаточно для того, чтобы эффективно пользоваться обобщениями в создаваемых на Java программах. Но у обобщений имеется немало особенностей, которые не нашли отражения в этой главе. Читатели, которых заинтересовала эта тема, вероятно, захотят узнать побольше о томвлиянии, которое обобщения оказывают на иерархию классов и, в частности, каким образом осуществляется сравнение типов при выполнении программы, как переопределяются методы и т.д. Все эти и многие другие вопросы употребления обобщений подробно освещены в книге Java. Полное руководство, 8-е издание, ИД “Вильямс”, 2012 г. ## Упражнение для самопроверки по материалу главы 13 1. Обобщения очень важны, поскольку они позволяют создавать код, который: a) обеспечивает типовую безопасность; b) пригоден для повторного использования; c) отличается высокой надежностью; d) обладает всеми перечисленными выше свойствами. 2. Можно ли указывать простой тип в качестве аргумента типа? 3. Как объявить класс FlightSched с двумя параметрами типа? 4. Измените ваш ответ на вопрос 3 таким образом, чтобы второй параметр типа обозначал подкласс, производный от класса Thread. 5. Внесите изменения в класс FlightSched таким образом, чтобы второй параметр типа стал подклассом первого параметра типа. 6. Что обозначает знак ? в обобщениях? 7. Может ли метасимвольный аргумент быть ограниченным? 8. У обобщенного метода My Gen () имеется один параметр типа, определяющий тип передаваемого ему аргумента. Этот метод возвращает также объект, тип которого соответствует параметру типа. Как должен быть объявлен метод My Gen () ? 9. Допустим, обобщенный интерфейс объявлен так, как показано ниже. interface IGenIF<T, V extends Т> { // ... ``` Составьте объявление класса MyClass, который реализует интерфейс iGenlF.

Допустим, имеется обобщенный класс Counter. Как создать объект его базового типа?

Существуют ли параметры типа на стадии выполнения программы?

Видоизмените ответ на вопрос 10 в упражнении по материалу главы 9 таким образом, чтобы сделать класс обобщенным. По ходу дела создайте интерфейс стека iGenStack, объявив в нем обобщенные методы push () и pop ().

Что обозначают угловые скобки (< >)?

Как упростить приведенную ниже строку кода в версии JDK 7?MyClass<Double,String> obj = new MyClass<Double,String>(1.1,"Hi");

Глава 14 Апплеты, события и прочее

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

Представление об апплетах

Архитектура апплетов

Создание заготовок апплетов

Инициализация и завершение апплетов

Перерисовка содержимого окон апплетов

Вывод данных в окне состояния

Передача параметров апплетам

Представление о классе Applet

Применение модели делегирования событий

Описание остальных ключевых слов Java

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

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

В конце этой главы приводится описание ключевых слов Java, которые еще не рассматривались в данной книге, например instanceof и native. Эти языковые средства предназначены для решения более сложных задач программирования на Java, а здесь они рассматриваются ради полноты представления об этом языке. Общее представление об апплетах

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