Текст книги "Java: руководство для начинающих (ЛП)"
Автор книги: Герберт Шилдт
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 35 (всего у книги 36 страниц)
Можно ли перегружать метод с аргументами переменной длины? Да, можно.
Приведите пример неоднозначного вызова перегружаемого метода с переменным числом аргументов. Ниже приведен один из вариантов перегружаемого метода с переменным числом аргументов, при вызове которого проявляется неоднозначность. double myMeth(double ... v ) { // ... double myMeth(double d, double ... v) { // ... Если попытаться вызвать метод myMeth () с одним аргументом следующим образом: myMeth(1.1); то компилятор не сможет определить, какой именно метод вызывается. Глава 7. Наследование
Имеет ли суперкласс доступ к членам подкласса? Имеет ли подкласс доступ к членам суперкласса? Нет, не имеет. Суперклассу ничего не известно о существовании подклассов. Подклассы действительно могут обращаться ко всем членам суперкласса, кроме тех, которые объявлены как закрытые (private).
Создайте подкласс Circle, производный от класса TwoDShape. В нем должен быть определен метод area (), вычисляющий площадь круга, а также конструктор с ключевым словом super для инициализации членов, унаследованных от класса TwoDShape. // Подкласс, производный от класса TwoDShape для формы круга, class Circle extends TwoDShape { // Конструктор по умолчанию Circle () { super(); } // Конструктор класса Circle Circle(double х) { super(x, "circle"); // вызвать конструктор суперкласса } // создать новый объект из имеющегося объекта Circle(Circle ob) { super(ob); // передать объект конструктору класса ?PwoDShape } double area () { return (getWidth() /2) (getWidth() / 2) 3.1416; } }
Как предотвратить обращение к членам суперкласса из подкласса? Для того чтобы предотвратить доступ к членам суперкласса из подкласса, эти члены следует объявить как закрытые (private).
Опишите назначение и два варианта использования ключевого слова super. Ключевое слово super используется в двух случаях. Во-первых, с его помощью вызывается конструктор суперкласса. В этом случае общая форма вызова имеет следующий вид: super (списокпараметров) ; И во-вторых, это ключевое слово обеспечивает доступ к членам суперкласса. Ниже приведена общая форма такого доступа. super.членкласса
Допустим, имеется следующая иерархия классов: class Alpha { ... class Beta extends Alpha { ... Class Gamma extends Beta { ... В каком порядке вызываются конструкторы этих классов при создании объекта класса Gamma? Конструкторы всегда вызываются в порядке наследования. Таким образом, при создании экземпляра класса Gamma будет сначала вызван конструктор Alpha, затем Beta и, наконец, Gamma.
Переменная ссылки на суперкласс может указывать на объект подкласса. Объясните, почему это важно и как это связано с переопределением методов? Когда переопределяемый метод вызывается по ссылке на суперкласс, его вариант определяется по типу объекта, на который делается ссылка.
Что такое абстрактный класс? Приложение А. Ответы на вопросы для самопроверки 573 Абстрактным называется такой класс, который содержит хотя бы один абстрактный метод.
Как предотвратить переопределение метода? И как предотвратить наследование класса? Для того чтобы метод нельзя было переопределить, его нужно объявить как final. А для того чтобы предотвратить наследование от класса, его следует объявить как final.
Объясните, каким образом механизмы наследования, переопределения методов и абстрактные классы используются для поддержки полиморфизма. Наследование, переопределение методов и абстрактные классы поддерживают полиморфизм и позволяют создать обобщенную структуру, реализуемую различными классами. Так, абстрактный класс определяет согласованный интерфейс, общий для всех реализующих его классов. Такой подход соответствует принципу “один интерфейс – множество методов”.
Какой класс является суперклассом всех остальных классов? Класс Object. П. Класс, который содержит хотя бы один абстрактный метод, должен быть объявлен абстрактным. Верно или не верно? Верно.
Какое ключевое слово следует использовать для создания именованной константы? Ключевое слово final. Глава 8. Пакеты и интерфейсы
Используя код, созданный в примере для опробования 8.1, поместите в пакет qpack интерфейс ICharQ и все три реализующие его класса. Класс IQDemo должен остаться в пакете, используемом по умолчанию. Покажите, как импортировать и использовать классы из пакета qpack. Для того чтобы включить интерфейс ICharQ и реализующие его классы в пакет qpack, следует поместить каждый из них в отдельный файл, объявить все классы, реализующие данный интерфейс, как public, а в начале каждого файла ввести следующий оператор: package qpack; После этого можно воспользоваться пакетом qpack, добавив в интерфейс IQDemo следующий оператор import: import qpack.*;
Что такое пространство имен? Почему так важна возможность его разделения на отдельные области в Java? Пространство имен – это область объявлений. Разделяя пространство имен на отдельные области, можно предотвратить конфликты имен.
Содержимое пакетов хранится в . каталогах
В чем отличие доступа, определяемого ключевым словом protected, от доступа по умолчанию? Член класса с доступом типа protected может быть использован в пределах текущего пакета, а также в подклассах данного класса, относящихся к любому пакету. А член класса с доступом по умолчанию может быть использован только в пределах текущего пакета.
Допустим, классы, содержащиеся в одном пакете, требуется использовать в другом пакете. Какими двумя способами можно этого добиться? Для того чтобы воспользоваться членом пакета, нужно указать его имя полностью или же импортировать этот член с помощью оператора import.
“Один интерфейс – множество методов” – главный принцип Java. Какое языковое средство лучше всего демонстрирует этот принцип? Этот принцип объектно-ориентированного программирования лучше всего демонстрирует интерфейс.
Сколько классов могут реализовать один и тот же интерфейс? Сколько интерфейсов может реализовать класс? Один интерфейс может быть реализован любым количеством классов. Класс может реализовать произвольное число интерфейсов.
Может ли один интерфейс наследовать другой интерфейс? Да, может. Механизм наследования распространяется и на интерфейсы.
Создайте интерфейс для класса Vehicle, рассмотренного в главе 7, назвав его IVehicle. interface IVehicle { // возвратить дальность действия транспортного средства int range(); // рассчитать объем топлива, требующегося // для прохождения заданного пути double fuelneeded(int miles); // Методы доступа к переменным экземпляра. int getPassengers(); void setPassengers(int p); int getFuelcap(); void setFuelcap(int f); int getMpg(); void setMpg(int m); }
Переменные, объявленные в интерфейсе, неявно считаются как static и final. Какие преимущества это дает? Переменные, объявленные в интерфейсе, могут служить в качестве именованных констант, общих для всех файлов программы. Доступ к ним обеспечивается путем импорта того интерфейса, в котором они объявлены.
Пакет, по существу, является контейнером для классов. Верно или не верно? Приложение А. Ответы на вопросы для самопроверки 575 Верно.
Какой стандартный пакет импортируется по умолчанию в любую программу на Java? Пакет java.lang. Глава 9. Обработка исключений
Какой класс находится на вершине иерархии исключений? На вершине иерархии исключений находится класс Throwable.
Объясните вкратце, как пользоваться ключевыми словами try и catch? Ключевые слова try и catch используются совместно. Операторы программы для отслеживания исключений помещаются в блок try. А перехват и обработка исключений осуществляются в блоке catch.
Какая ошибка допущена в приведенном ниже фрагменте кода? II ... vals[18] = 10; catch (ArraylndexOutOfBoundsException exc) { // обработать ошибку } Блоку catch не предшествует блок try.
Что произойдет, если исключение не будет перехвачено? Если исключение не будет перехвачено, произойдет аварийное завершение программы.
Какая ошибка допущена в приведенном ниже фрагменте кода? class A extends Exception { ... class В extends А { ... II ... try { II ... } catch (A exc) { ... } catch (B exc) { ... } В данном фрагменте кода оператор catch для суперкласса предшествует оператору catch для подкласса. А поскольку оператор catch для суперкласса может обработать также исключения, относящиеся к подклассу, то в программе окажется код, недоступный для выполнения.
Может ли внутренний блок catch повторно генерировать исключение, которое будет обработано во внешнем блоке catch? Да, исключения могут генерироваться повторно.
Блок finally – последний фрагмент кода, выполняемый перед завершением программы. Верно или неверно? Обоснуйте свой ответ. Неверно. Блок finally выполняется по завершении блока try.
Исключения какого типа необходимо явно объявлять с помощью оператора throws, включаемого в объявление метода? С помощью оператора throws объявляются все исключения, кроме Runtime Exception и Error.
Какая ошибка допущена в приведенном ниже фрагменте кода? class MyClass { // ... } // ... throw new MyClass(); Класс MyClass не является производным от класса Throwable. С помощью оператора throw могут генерироваться лишь те исключения, которые являются подклассами, производными от класса Throwable.
Отвечая на вопрос 3 упражнения для самопроверки по материалу главы 6, вы создали класс Stack. Добавьте в него специальные исключения для реагирования на попытку поместить элемент в переполненный стек и извлечь элемент из пустого стека. // Исключение, возникающее при переполнении стека, class StackFullException extends Exception { int size; StackFullException (int s) { size = s; } public String toString() { return "nStack is full. Maximum size is " + size; } } // Исключение, возникающее при обращении к пустому стеку, class StackEmptyException extends Exception { public String toString () { return "nStack is empty."; } } // Класс, реализующий стек для хранения символов, class Stack { private char stck[]; // Массив для хранения элементов стека private int tos; // Вершина стека // построить пустой стек заданного размера Stack(int size) { stck = new char[size]; // выделить память для стека tos = 0; } // построить один стек из другого стека Stack(Stack ob) { tos = ob.tos; stck = new char[ob.stck.length]; Приложение А. Ответы на вопросы для самопроверки 577 // скопировать элементы for(int i=0; i < tos; i++) stck[i] = ob.stck[i]; } // построить стек с исходными значениями Stack(char а [ ]) { stck = new char[a.length]; for(int i = 0; i < a.length; i++) { try { push (a [i]); } catch(StackFullException exc) { System.out.println(exc); } } } // поместить символы в стек void push(char ch) throws StackFullException { if(tos==stck.length) throw new StackFullException(stck.length); stck[tos] = ch; tos++; } // извлечь символы из стека char pop() throws StackEmptyException { if(tos==0) throw new StackEmptyException(); tos – ; return stck[tos]; } }
Какими тремя способами можно сгенерировать исключение? Исключение может быть сгенерировано в результате ошибки в виртуальной машине Java, ошибки в программе или явным образом с помощью оператора throw.
Назовите два подкласса, производных непосредственно от класса Throwable. Классы Error и Exception
Что такое многократный перехват? Многократным называется такой перехват, который позволяет перехватывать два и больше исключений одним оператором catch.
Следует ли перехватывать в программе исключения типа Error? Нет, не следует. Глава 10. Ввод-вывод данных
Для чего в Java определены как байтовые, так и символьные потоки? Байтовые потоки с самого начала были определены в Java. Они особенно удобны для ввода-вывода двоичных данных и поддерживают произвольный доступ к ним в файлах. А символьные потоки оптимизированы для представления в уникоде.
Как известно, ввод-вывод данных на консоль осуществляется в текстовом виде. Почему же в Java для этой цели используются байтовые потоки? Стандартные потоки ввода-вывода System, in, System.out и System.err были определены в Java прежде символьных потоков.
Как открыть файл для чтения байтов? Ниже приведен один из способов открытия файла для ввода данных типа byte. FilelnputStream fin = new FilelnputStream("test");
Как открыть файл для чтения символов? Ниже приведен один из способов открытия файла для ввода символов. FileReader fr = new FileReader("test");
Как открыть файл для ввода-вывода с произвольным доступом? Ниже приведен один из способов открытия файла для ввода-вывода с произвольным доступом. randfile = new RandomAccessFile("test", "rw");
Как преобразовать числовую строку "123.23" в двоичный эквивалент? Для того чтобы преобразовать числовую строку в двоичный эквивалент, следует воспользоваться одним из методов синтаксического анализа, определенных в классах оболочек типов, например Integer или Double.
Напишите программу, которая будет копировать текстовые файлы. Видоизмените ее таким образом, чтобы все пробелы заменялись дефисами. Используйте при написании программы классы, представляющие байтовые потоки, а также традиционный способ закрытия файла явным вызовом метода close (). / Копирование текстового файла с заменой пробелов дефисами. В этой версии программы используются байтовые потоки. Для того чтобы воспользоваться этой программой, укажите в командной строке имена исходного и целевого файлов. Например: java Hyphen source target / import java.io.*; class Hyphen { public static void main(String args[]) { int i; FilelnputStream fin = null; FileOutputStream fout = null; Приложение А. Ответы на вопросы для самопроверки 579 // проверить сначала, указаны ли оба файла if(args.length !=2 ) { System.out.println(«Usage: Hyphen From To»); return; } // скопировать файл и заменить в нем пробелы дефисами try { fin = new FilelnputStream(args[0]); fout = new FileOutputStream(args[1]); do { i = fin.read(); // преобразовать пробел в дефис if((char)i == ' ') i = if(i != -1) fout.write(i); } while(i != -1); } catch(IOException exc) { System.out.println("I/O Error: " + exc); } finally { try { if (fin != null) fin.closeO; } catch(IOException exc) { System.out.println(«Error closing input file.»); } try { if(fin != null) fout.close(); } catch(IOException exc) { System.out.println(«Error closing output file.»); } } } }
Перепишите программу, созданную в ответ на предыдущий вопрос, таким образом, чтобы в ней использовались классы, представляющие символьные потоки. На этот раз воспользуйтесь оператором try с ресурсами для автоматического закрытия файла. /* Копирование текстового файла с заменой пробелов дефисами. В этой версии программы используются символьные потоки. Для того чтобы воспользоваться этой программой, укажите в командной строке имена исходного и целевого файлов. Например: java Hyphen2 source target Для компиляции этого кода требуется JDK 7
или более поздняя версия данного комплекта. / import java.io.; class Hyphen2 { public static void main(String args[]) throws IOException { int i; // проверить сначала, указаны ли оба файла if(args.length !=2 ) { System.out.println(«Usage: CopyFile From To»); return; } // скопировать файл и заменить в нем пробелы дефисами, // используя оператор try с ресурсами try (FileReader fin = new FileReader(args[0]); FileWriter fout = new FileWriter(args[1])) { do { i = fin.read(); // преобразовать пробел в дефис if((char)i == • ') i = if(i != -1) fout.write(i); } while(i != —1); } catch(IOException exc) { System.out.println("I/O Error: " + exc); } } }
К какому типу относится поток System. in? К типу InputStream.
Что возвращает метод read () из класса InputStream по достижении конца потока? Значение -1.
Поток какого типа используется для чтения двоичных данных? Поток типа DatalnputStream.
Классы Reader и Writer находятся на вершине иерархии классов символьного ввода-вывода
Оператор try без ресурсов служит для . автоматического управления ресурсами
Если для закрытия файла используется традиционный способ, то это лучше всего делать в блоке finally. Верно или неверно? Верно. Глава 11. Многопоточное программирование
Каким образом имеющиеся в Java средства многопоточного программирования позволяют писать более эффективные программы? Средства многопоточного программирования дают возможность использовать периоды простоя, наступающие практически в любой программе. Когда операции в одном потоке по каким-то причинам не выполняются, в действие вступают другие потоки. В многоядерных системах два и больше потоков могут исполняться одновременно.
Для поддержки многопоточного программирования в Java предусмотрен класс и интерфейс . Для поддержки многопоточного программирования в Java предусмотрен класс Thread и интерфейс Runnable.
В каких случаях следует отдать предпочтение расширению класса Thread над реализацией интерфейса Runnable? Подклассы, производные от класса Thread, целесообразно создавать в тех случаях, когда, помимо метода run (), требуется переопределить другие методы данного класса.
Покажите, как с помощью метода j о in () можно организовать ожидание завершения потокового объекта MyThrd. MyThrd.join()
Покажите, как установить приоритет потока MyThrd на три уровня выше нормального приоритета. MyThrd.setPriority(Thread.N0RM_PRI0RITY+3);
Что произойдет, если в объявлении метода указать ключевое слово synchronized? Если указать ключевое слово synchronized в объявлении метода, то в каждый момент времени этот метод будет вызываться только в одном потоке для любого заданного объекта его класса.
Методы wait () и notify () служат для . взаимодействия потоков
Внесите в класс TickTock изменения для организации настоящего отчета времени. Первую половину секунды должен занимать вывод на экран слова "Tick", а вторую – вывод слова "Tock". Таким образом, сообщение "Tick-Tock" должно соответствовать одной секунде отсчитываемого времени. (Время переключения контекстов можно не учитывать.) Для организации отчета времени достаточно ввести в классе TickTock вызовы метода sleep (), как показано ниже. // Вариант класса TickTock, в который введены вызовы // метода sleep() для организации отсчета времени. class TickTock { String state; // Состояние часов synchronized void tick(boolean running) { 582 Javc,/: руководство для начинающих, 5-е издание if(!running) { // остановить часы state = "ticked"; notifyO; // уведомить ожидающие потоки return; } System.out.print("Tick "); // ожидать 1/2 секунды try { Thread.sleep(500); } catch(InterruptedException exc) { System.out.println("Thread interrupted."); } state = "ticked"; // установить текущее состояние после такта "тик" notifyO; // разрешить выполнение метода tock() try { while(!state.equals("tocked")) wait (); // ожидать завершения метода tock() } catch(InterruptedException exc) { System.out.println("Thread interrupted."); } synchronized void tock(boolean running) { if(!running) { // остановить часы state = "tocked"; notifyO; // уведомить ожидающие потоки return; } System.out.println("Tock"); // ожидать 1/2 секунды try { Thread.sleep(500); } catch(InterruptedException exc) { System.out.println("Thread interrupted."); } state = "tocked"; // установить текущее состояние после такта "так" notifyO; // разрешить выполнение метода tick() try { while(!state.equals("ticked")) wait (); // ожидать завершения метода tick() } catch(InterruptedException exc) { System.out.println("Thread interrupted."); } Приложение А. Ответы на вопросы для самопроверки 583 } }
Почему в новых программах на Java не следует применять методы suspend (), resume() и stop()? Методы suspend (), resume () и stop () не рекомендуется применять, поскольку они могут стать причиной серьезных осложнений при выполнении программы.
С помощью какого метода из класса Thread можно получить имя потока? С помощью метода getName ().
Какое значение возвращает метод is Alive () ? Он возвращает логическое значение true, если вызывающий поток исполняется, или логическое значение false, если поток завершен. Глава 12. Перечисления, автоупаковка,
статический импорт и аннотации
Константы перечислимого типа иногда называются самотипизированными. Что это означает? Часть “само” в термине самотипизированный означает тип перечисления, в котором определена константа. Следовательно, константа перечислимого типа является объектом того перечисления, в которое она входит.
Какой класс автоматически наследуют перечисления? Все перечисления наследуют от класса Enum.
Напишите для приведенного ниже перечисления программу, в которой метод values () служит для отображения списка констант и их значений. enum Tools { SCREWDRIVER, WRENCH, HAMMER, PLIERS } Это задание имеет следующее решение: enum Tools { SCREWDRIVER, WRENCH, HAMMER, PLIERS } class ShowEnum { public static void main(String args[]) { for(Tools d : Tools.values()) System.out.print(d + " has ordinal value of " + d.ordinal() + 'n'); } }
Программу, имитирующую автоматизированный светофор и созданную в примере для опробования 12.1, можно усовершенствовать, внеся ряд простых изменений, чтобы выгодно воспользоваться возможностями перечислений. В исходной версии этой программы продолжительность отображения каждого цвета светофора регулировалась в классе Traf ficLightSimulator, причем величины задержек были жестко запрограммированы в методе run (). Измените исходный код программы 584 Jav, 7: руководство для начинающих, 5-е издание таким образом, чтобы продолжительность отображения каждого цвета светофора задавалась константами перечислимого типа Traf f icLightColor. Для этого вам понадобятся конструктор, переменная экземпляра, объявленная как private, а также метод getDelay (). Подумайте о том, как еще можно улучшить данную программу. (Подсказка: попробуйте отказаться от оператора switch и воспользоваться порядковыми значениями каждого цвета для переключения светофора.) Усовершенствованная версия программы, имитирующей работу светофора, приведена ниже. В нее внесены два существенных изменения. Во-первых, величина задержки переключения связана теперь со значением перечислимого типа, что улучшает структуру кода. И во-вторых, в методе run () удалось обойтись без оператора switch. Вместо этого методу sleep () теперь передается вызов tic. getDelay (), и благодаря этому автоматически устанавливается задержка, соответствующая текущему цвету светофора. // Усовершенствованная версия программы, имитирующей работу светофора. // Величины задержки теперь хранятся в классе TrafficLightColor. // Перечисление цветов переключения светофора, enum TrafficLightColor { RED(12000), GREEN(10000), YELLOW(2000); private int delay; TrafficLightColor(int d) { delay = d; } int getDelay() { return delay; } } // Имитация автоматизированного светофора, class TrafficLightSimulator implements Runnable { private Thread thrd; // Поток для имитации светофора private TrafficLightColor tic; // Текущее значение цвета boolean stop = false; // Остановка имитации, если истинно boolean changed = false; // Переключение светофора, если истинно TrafficLightSimulator(TrafficLightColor init) { tic = init; thrd = new Thread(this); thrd.start(); } TrafficLightSimulator() { tic = TrafficLightColor.RED; thrd = new Thread(this); thrd.start(); } // Запуск имитации автоматизированного светофора. Приложение А. Ответы на вопросы для самопроверки 585 public void run() { while(!stop) { // По сравнению с предыдущей версией программы // код значительно упростился! try { Thread.sleep(tlc.getDelay()); } catch(InterruptedException exc) { System.out.println(exc); } changeColor (); } } // Переключение цвета светофора, synchronized void changeColor() { switch(tic) { case RED: tic = TrafficLightColor.GREEN; break; case YELLOW: tic = TrafficLightColor.RED; break; case GREEN: tic = TrafficLightColor.YELLOW; } changed = true; notify(); // уведомить о переключении цвета светофора } // Ожидание переключения цвета светофора, synchronized void waitForChange() { try { while(!changed) wait(); // ожидать переключения цвета светофора changed = false; } catch(InterruptedException exc) { System.out.println(exc); } } // Возврат текущего цвета. TrafficLightColor getColor() { return tic; } // Прекращение имитации светофора, void cancel() { stop = true; class TrafficLightDemo { public static void main(String args[]) { TrafficLightSimulator tl = new TrafficLightSimulator(TrafficLightColor.GREEN); for(int i=0; i < 9; i++) { System.out.println(tl.getColor()); tl.waitForChange(); } tl.cancel (); } }
Что такое упаковка и распаковка? В каких случаях производится автоупаковка и автораспаковка? Упаковка означает включение значения простого типа в объект оболочки, а распаковка – извлечение значения из объекта оболочки. Автоупаковка означает автоматическую упаковку значения без явного создания объекта, тогда как при автораспаковке значение простого типа автоматически извлекается из объекта оболочки без явного вызова соответствующего метода, например intValue ().
Измените следующий фрагмент кода таким образом, чтобы в нем производилась автоупаковка: Short val = new Short(123); Это задание имеет следующее решение: Short val = 123;
Объясните, что такое статический импорт? Статический импорт означает размещение статических членов класса или интерфейса в глобальном пространстве имен. Это позволяет использовать статические члены без указания имени соответствующего класса или интерфейса.
Какие действия выполняет приведенный ниже оператор? import static java.lang.Integer.parselnt; Этот оператор помещает в глобальное пространство имен метод parselnt () из класса оболочки типа Integer.
Следует ли употреблять статический импорт от случая к случаю или желательно импортировать статические члены всех классов? Статический импорт уместен только в отдельных случаях. Если доступным окажется слишком много статических членов, это может привести к конфликтам имен и нарушению структуры кода.
Синтаксис аннотации основывается на . интерфейсе
Какая аннотация называется маркером? Маркер – это аннотация без аргументов.
Аннотации применимы только к методам. Верно или неверно? Неверно. Любое объявление может быть аннотировано. Глава 13. Обобщения
Обобщения очень важны, поскольку они позволяют создавать код, который: а) обеспечивает типовую безопасность; б) пригоден для повторного использования; в) отличается высокой надежностью; г) обладает всеми перечисленными выше свойствами. Ответ: г) код обладает всеми перечисленными выше свойствами.
Можно ли указывать простой тип в качестве аргумента типа? Нет, нельзя. В качестве аргументов типа можно указывать только типы объектов.
Как объявить класс FlightSched с двумя параметрами типа? Это задание имеет следующее решение: class FlightSched {
Измените ваш ответ на вопрос 3 таким образом, чтобы второй параметр типа обозначал подкласс, производный от класса Thread. Это задание имеет следующее решение: class FlightSched {
Внесите изменения в класс FlightSched таким образом, чтобы второй параметр типа стал подклассом первого параметра типа. Это задание имеет следующее решение: class FlightSchedCT, V extends Т> {
Что обозначает знак ? в обобщениях? Знак ? обозначает метасимвольный аргумент, который соответствует любому допустимому типу.
Может ли метасимвольный аргумент быть ограниченным? Да. Метасимвольный аргумент может ограничиваться как сверху, так и снизу.
У обобщенного метода My Gen () имеется один параметр типа, определяющий тип передаваемого ему аргумента. Этот метод возвращает также объект, тип которого соответствует параметру типа. Как должен быть объявлен метод MyGen () ? Это задание имеет следующее решение: <Т> Т MyGen(Т о) {//.. .
Допустим, обобщенный интерфейс объявлен так, как показано ниже, interface IGenlFCT, V extends Т> { // ... Составьте объявление класса MyClass, который реализует интерфейс I Gen IF. Это задание имеет следующее решение: class MyClass implements IGenlFCT, V> { // ...
Допустим, имеется обобщенный класс Counter. Как создать объект его базового типа? Для того чтобы получить базовый тип из обобщенного класса Counter, достаточно указать его имя, не обозначая тип, как показано ниже. Counter х = new Counter; 588 Java 7r руководство для начинающих, 5-е издание
Существуют ли параметры типа на стадии выполнения программы? Нет. Все параметры типа удаляются на стадии компиляции и заменяются соответствующими приводимыми типами. Этот процесс называется стиранием.
Видоизмените ответ на вопрос 10 в упражнении по материалу главы 9 таким образом, чтобы сделать класс обобщенным. По ходу дела создайте интерфейс стека IGenStack, объявив в нем обобщенные методы push () и pop (). // Обобщенный стек. interface IGenStack { void push(T obj) throws StackFullException; T pop() throws StackEmptyException; } // Исключение, возникающее при переполнении стека, class StackFullException extends Exception { int size; StackFullException(int s) { size = s; } public String toString() { return "nStack is full. Maximum size is " + size; } } // Исключение, возникающее при обращении к пустому стеку, class StackEmptyException extends Exception { public String toString() { return "nStack is empty.”; } } // Класс, реализующий стек для хранения объектов обобщенного типа, class GenStack implements IGenStack { private T stck[]; // Массив для хранения элементов стека private int tos; // Вершина стека // построить пустой стек заданного размера GenStack(T[] stckArray) { stck = stckArray; tos = 0; } // построить один стек из другого стека GenStack(T[] stckArray, GenStack ob) { tos = ob.tos; stck = stckArray; try { Приложение А. Ответы на вопросы для самопроверки 589 if(stck.length < ob.stck.length) throw new StackFullException(stck.length); } catch(StackFullException exc) { System.out.println(exc); } // скопировать элементы for(int i=0; i < tos; i++) > stck[i] = ob.stck[i]; } // построить стек с исходными значениями GenStack(T[] stckArray, Т[] а) { stck = stckArray; for(int i = 0; i < a.length; i++) { try { push(a [i]); } catch(StackFullException exc) { System.out.println(exc); } } } // поместить объекты в стек public void push(T obj) throws StackFullException { if(tos==stck.length) throw new StackFullException(stck.length); stck[tos] = obj; tos++; } // извлечь объекты из стека public Т pop() throws StackEmptyException { if(tos==0) throw new StackEmptyException(); tos—; return stck[tos]; } } // продемонстрировать применение класса GenStack class GenStackDemo { public static void main(String args[]) { // создать пустой стек на 10 элементов типа Integer Integer iStore[] = new Integer[10]; GenStack stkl = new GenStack (i'Store) ; // построить стек из массива String name[] = {"One", "Two", "Three"}; String strStore[] = new String[3]; GenStack stk2 = new GenStack(strStore, name); String str; int n; try { // поместить ряд значений в стек stkl for(int i=0; i < 10; i++) stkl.push(i); } catch(StackFullException exc) { System.out.println(exc); } // построить один стек из другого стека String strStore2[] = new String[3]; GenStack stk3 = new GenStack(strStore2, stk2); try { // отобразить стеки System.out.print("Contents of stkl: "); for(int i=0; i < 10; i++) { n = stkl.pop(); System.out.print(n + " "); } System.out.println("n"); System.out.print("Contents of stk2: "); for(int i=0; i < 3; i++) { str = stk2.pop(); System.out.print(str + " "); } System.out.println("n"); System.out.print("Contents of stk3: "); for(int i=0; i < 3; i++) { str = stk3.pop(); System.out.print(str + " "); } } catch(StackEmptyException exc) { System.out.println(exc); } System.out.println(); } } Приложение А. Ответы на вопросы для самопроверки 591