Skip to content

Latest commit

 

History

History
1898 lines (1781 loc) · 122 KB

appendix_a.md

File metadata and controls

1898 lines (1781 loc) · 122 KB

Приложение А

Ответы на вопросы для самопроверки

Глава 1. Основы Java

  1. Что такое байт-код и почему он так важен для интернет-программирования на языке Java? Байт-код — это высокооптимизированный набор инструкций, выполняемых под управлением интерпретатора Java. Байт-код позволяет добиться переносимости и безопасности программ, написанных на этом языке программирования.

  2. Каковы три основных принципа объектно-ориентированного программирования? Инкапсуляция, полиморфизм и наследование.

  3. С чего начинается выполнение программы на Java? Выполнение программы на Java начинается с метода main ().

  4. Что такое переменная? Переменная — это именованная область памяти. Содержимое переменной может изменяться в процессе выполнения программы.

  5. Какое из перечисленных ниже имен переменных недопустимо?

    A. count B. $count C. count27 D. 67count

    Недопустимо имя переменной 67count (пункт D). Имя переменной не может начинаться с цифры.

  6. Как создать однострочный комментарий? И как создать многострочный комментарий? Однострочные комментарии должны начинаться с символов / /.В этом случае комментариями считаются эти и все последующие символы до конца строки. А многострочные комментарии должны начинаться символами / * и заканчиваться символами */.

  7. Как выглядит общая форма условного оператора if? И как выглядит общая форма цикла for? Общая форма оператора if выглядит следующим образом:

    if (условие) оператор;
    

    А общая форма цикла for имеет следующий вид:

    for (инициализация; условие; итерация) оператор;
    
  8. Как создать кодовый блок? Кодовый блок должен начинаться с символа { и завершаться символом }.

  9. Сила тяжести на Луне составляет около 17% земной. Напишите программу, которая вычисляла бы ваш вес на Луне.

    /*
        Вычисление веса на Луне.
        Присвоить ее исходному файлу имя Moon.java.
    */
    class Moon {
        public static void main(String args[]) {
        double earthweight; // Вес на Земле
        double moonweight; // Вес на Луне
        earthweight = 165;
        moonweight = earthweight * 0.17;
        System.out.println(earthweight +
                           " earth-pounds is equivalent to " +
                           moonweight + " moon-pounds.");
        }
    }
    
  10. Видоизмените программу, созданную в примере для опробования 1.2, таким образом, чтобы она выводила таблицу преобразования дюймов в метры. Выводите значения длины до 12 футов через каждый дюйм. После каждых 12 дюймов выводите пустую строку. (Один метр приблизительно равен 39,37 дюйма.)

    /*
    Эта программа отображает таблицу преобразования дюймов в метры.
    Присвоить ее исходному файлу имя InchToMeterTable.java.
    */
    class InchToMeterTable {
        public static void main(String args[]) {
            double inches, meters;
            int counter;
            counter = 0;
            for(inches = 1; inches <= 144; inches++) {
                meters = inches / 39.37; // преобразовать в метры
                System.out.println(inches + " inches is " +
                                   meters + " meters.");
                counter++;
                // Каждая 12-я выводимая строка должна быть пустой
                if(counter == 12) {
                    System.out.println();
                    counter =0; // сбросить счетчик строк
                }
            }
        }
    }
    
  11. Если при вводе кода программы вы допустите опечатку, то какого рода сообщение об ошибке вы получите? Сообщение о синтаксической ошибке.

  12. Имеет ли значение, в каком именно месте строки находится оператор? Не имеет. В Java допускается произвольное форматирование исходного кода.

Глава 2. Введение в типы данных и операторы

  1. Почему в Java строго определены диапазоны допустимых значений и области действия простых типов? Диапазоны допустимых значений и области действия простых типов строго определены в Java для того, чтобы обеспечить переносимость программ с одной платформы на другую.
  2. Что собой представляет символьный тип в Java и чем он отличается от символьного типа в ряде других языков программирования? Символьный тип задается ключевым словом char. В Java для представления символов применяется уникод (Unicode), в отличие от многих других языков программирования, в которых для этой цели применяется код ASCII.
  3. Переменная типа boolean может иметь любое значение, поскольку любое ненулевое значение интерпретируется как истинное. Верно или неверно? Неверно. Переменная типа boolean может принимать лишь одно из двух логических значений: true или false.
  4. Допустим, результат выполнения программы выглядит следующим образом:
    One
    Two
    Three
    
    Напишите строку кода с вызовом метода println(), где этот результат выводится в одной символьной строке.
    System.out.println("One\nTwo\nThree");
    
  5. Какая ошибка допущена в следующем фрагменте кода:
    for(i = 0; i < 10; i++) {
        int sum;
        sum = sum + i;
    }
    System.out.println("Sum is: " + sum);
    
    В этом фрагменте кода имеются две существенные ошибки. Во-первых, переменная sum создается на каждом шаге цикла for, а следовательно, в промежутке между последовательными итерациями предыдущее значение подсчитываемой суммы не будет сохраняться в этой переменной. И во-вторых, переменная sum недоступна за пределами кодового блока, в котором она объявлена. Поэтому ссылка на нее при вызове метода println () недопустима.
  6. Поясните отличие между префиксной и постфиксной формами оператора инкремента. Если оператор инкремента предшествует операнду, исполняющая система Java выполнит операцию до извлечения значения операнда и использования его в остальной части выражения. Если же оператор инкремента следует за операндом, исполняющая система сначала извлечет значение операнда и лишь затем инкрементирует сам операнд.
  7. Покажите, каким образом укороченный логический оператор И может предотвратить деление на нуль.
    if((b != 0) && (val / b))   ...
    
  8. К какому типу продвигаются типы byte и short при вычислении выражения? В выражении типы byte и short продвигаются к типу int.
  9. Когда возникает потребность в явном приведении типов? Явное приведение типов требуется при обращении с несовместимыми типами или в том случае, если преобразование типов приводит к сужению диапазона допустимых значений.
  10. Напишите программу, которая находила бы простые числа в пределах от 2 до 100.
    // Нахождение простых чисел в пределах от 2 до 100.
    class Prime {
        public static void main(String args[]) {
            int i, j;
            boolean isprime;
            for(i=2; i < 100; i++) {
                isprime = true;
                // проверить, делится ли число без остатка
                for(j=2; j < i/j; j++)
                    // если число делится без остатка, значит, оно простое
                    if ( (i%j) == 0) isprime = false;
                if(isprime)
                    System.out.println(i + " is prime.");
            }
        }
    }
    
  11. Влияют ли лишние скобки на эффективность выполнения программ? Нет, не влияют.
  12. Определяет ли кодовый блок область действия переменных? Да, определяет.

Глава 3. Управляющие операторы

  1. Напишите программу, которая вводила бы символы с клавиатуры до тех пор, пока не встретится точка. Предусмотрите в программе счетчик числа пробелов. Сведения о количестве пробелов должны выводиться в конце программы.
    // Подсчет пробелов,
    class Spaces {
        public static void main(String args[])
            throws java.io.IOException {
            char ch;
            int spaces = 0;
            System.out.println("Enter a period to stop.");
            do {
                ch = (char) System.in.read();
                if(ch == 1 ') spaces++;
            } while (ch ! =  '.');
            System.out.println("Spaces: " + spaces);
        }
    }
    
  2. Какова общая форма многоступенчатой конструкции if-else-if?
    if(условие)
    оператор;
    else if{условие)
    оператор;
    else if(условие)
    оператор;
    else
    оператор;
    
  3. Допустим, имеется следующий фрагмент кода:
    if (х < 10)
    if(у > 100) {
    if(!done) х = z;
    else у = z;
    }
    else System.out.println("error"); // что если?
    
    С каким из операторов if связан последний оператор else? Последний оператор else соответствует билижайшему оператору if того же уровня, т.е. if (у > 100).
  4. Напишите цикл for, в котором перебирались бы значения от 1000 до 0 с шагом -2.
    for(int i = 1000; i >= 0; i -= 2) // ...
    
  5. Корректен ли следующий фрагмент кода?
    for(int i = 0; i < num; i++)
    sum += i;
    count = i;
    

Нет, не корректен. Переменная i недоступна за пределами цикла for, в котором она объявлена. 6. Какие действия выполняет оператор break? Опишите оба рарианта этого оператора. Оператор break без метки вызывает немедленное завершение текущего цикла или выражения switch. А оператор break с меткой передает управление в конец помеченного блока. 7. Какое сообщение будет выведено после выполнения оператора break в приведенном ниже фрагменте кода? for(i = 0; i < 10; i++) { while(running) { if(x<y) break; // ... } System.out.println("after while"); } System.out.println("After for"); После выполнения оператора break будет выведено сообщение "after while" (после цикла while). 8. Что будет выведено на экран в результате выполнения следующего фрагмента кода? ```` for (int i = 0; i<10; i++) { System.out.print(i + " "); if((i%2) == 0) continue; System.out.println(); } На экране появится следующий результат: о 1 2 3 4 5 6 7 8 9 9. Итерационное выражение для цикла for не обязательно должно изменять переменную цикла на фиксированную величину. Эта переменная может принимать произвольные значения. Напишите программу, использующую цикл for для вывода чисел в геометрической прогрессии 1, 2, 4, 8, 16, 32 и т.д. ``` /* Применение цикла for для формирования геометрической прогрессии 1, 2, 4, 8, 16, 32 и т.д. */ class Progress { public static void main(String args[]) { for(int i = 1; i < 100; i += i) System.out.print(i + " "); } } ``` 10. Код ASCII-символов нижнего регистра отличается от кода соответствующих символов верхнего регистра на величину 32. Следовательно, для преобразования строчной буквы в прописную нужно уменьшить ее код на 32. Используйте это обстоятельство для написания программы, осуществляющей ввод символов с клавиатуры. При выводе результатов данная программа должна преобразовывать строчные буквы в прописные, а прописные — в строчные. Остальные символы не должны изменяться. Работа программы должна завершаться после того, как пользователь введет с клавиатуры точку. И наконец, сделайте так, чтобы программа отображала число символов, для которых был изменен регистр. ``` // Смена регистра символов, class CaseChg { public static void main(String args[]) throws java.io.IOException { char ch; int changes = 0; System.out.println("Enter period to stop."); do { ch = (char) System.in.read(); if(ch >= 'a' & ch <= 'z') { ch -= 32; changes++; System.out.println(ch); } else if(ch >= 'A' & ch <= 'Z') { ch += 32; changes++; System.out.println(ch); } } while(ch != '.'); System.out.println("Case changes: " + changes); } } ``` 11. Что такое бесконечный цикл? Бесконечным называется такой цикл, выполнение которого не оканчивается. 12. Должна ли метка, используемая вместе с оператором break, быть определена в кодовом блоке, содержащем этот оператор? Да, должна.

Глава 4. Введение в классы, объекты и методы

  1. В чем отличие класса от объекта? Класс — это абстрактное логическое описание формы и поведения объекта. А объект — это вещественный экземпляр класса.
  2. Как определяется класс? Класс определяется с помощью ключевого слова class. В операторе class указываются код и данные, составляющие класс.
  3. Чью собственную копию содержит каждый объект? Каждый объект класса содержит собственную копию переменных экземпляра этого класса.
  4. Покажите, как объявить объект counter класса MyCounter, используя два отдельных оператора.
    MyCounter counter;
    counter = new MyCounter();
    
  5. Как должен быть объявлен метод myMeth, принимающий два параметра а и b типа int и возвращающий значение типа double?
    double myMeth(int a, int b) { // ...
    
  6. Как должно завершаться выполнение метода, возвращающего некоторое значение? Для завершения метода служит оператор return. Он же передает возвращаемое значение вызывающей части программы.
  7. Каким должно быть имя конструктора? Имя конструктора должно совпадать с именем класса.
  8. Какие действия выполняет оператор new? Оператор new выделяет память для объекта и выполняет инициализацию объекта, используя конструктор соответствующего класса.
  9. Что такое “сборка мусора” и какие действия она выполняет? Зачем нужен метод finalize()? “Сборка мусора” — это механизм удаления неиспользуемых объектов для повторного использования памяти, освобождаемой от объектов. Метод finalize () вызывается для объекта непосредственно перед его удалением из памяти.
  10. Что означает ключевое слово this? Ключевое слово this означает ссылку на объект, для которого вызывается метод. Она автоматически передается методу.
  11. Может ли конструктор иметь один или несколько параметров? Да, может.
  12. Если метод не возвращает значения, то как следует объявить тип этого метода? Как void.

Глава 5. Дополнительные сведения о типах данных и операторах

  1. Покажите два способа объявления одномерного массива, состоящего из 12 элементов типа double.

    double х[] = new double[12];
    double[] x = new double[12];
    
  2. Покажите, как инициализировать одномерный массив целочисленными значениями от 1 до 5.

    int х[] = { 1, 2, 3, 4, 5 };
    
  3. Напишите программу, в которой массив используется для нахождения среднего арифметического десяти значений типа double. Используйте любые десять чисел.

    // Среднее арифметическое 10 значений типа double,
    class Avg {
        public static void main(String args[]) {
            double nums[] = { 1.1, 2.2, 3.3, 4.4, 5.5,
                              6.6, 7.7, 8.8, 9.9, 10.1 };
            double sum = 0;
            for(int i=0; i < nums.length; i++)
                sum += nums[i];
            System.out.println("Average: " + sum / nums.length);
        }
    }
    
  4. Измените программу, созданную в примере для опробования 5.1, таким образрм, чтобы она сортировала массив символьных строк. Продемонстрируйте ее работоспособность.

    // Демонстрация пузырьковой сортировки строк,
    class StrBubble {
        public static void main(String args[]) {
            String strs[] = {
                "this", "is", "a", "test",
                "of", "a", "string", "sort"
            };
            int a, b;
            String t;
            int size;
            size = strs.length; // Количество сортируемых элементов
            // отобразить исходный массив
            System.out.print("Original array is:");
            for (int i=0; i < size; i++)
                System.out.print(" " + strs[i]);
            System.out.println();
            // Пузырьковая сортировка строк.
            for(a=l; a < size; a++)
                for(b=size-l; b >= a; b—)   {
                    // поменять элементы местами при нарушении порядка их следования
                    if(strs[b—1].compareTo(strs[b]) > 0) {
                    t = strs[b-1];
                    strs[b-l] = strs[b];
                    strs[b] = t;
                    }
                }
            // отобразить отсортированный массив
            System.out.print("Sorted array is:");
            for (int i=0; i < size; i++)
                System.out.print(" " + strs[i]);
            System.out.println();
        }
    }
    
  5. В чем отличие методов indexOf () и lastIndexOf () из класса String? Метод indexOf () находит первое вхождение указанной подстроки, а метод lastlndexOf () — ее последнее вхождение в текущей символьной строке.

  6. Все символьные строки являются объектами типа String. Покажите, как вызываются методы length () и charAt () для строкового литерала ”1 like Java" (Мне нравится Java). Как ни странно, приведенный ниже вызов метода length () вполне допустим.

    System.out.println("I like Java".length());
    

    В результате этого вызова на экран выводится значение 11. Аналогичным образом вызывается и метод charAt ().

  7. Расширьте класс Encode таким образом, чтобы в качестве ключа шифрования использовалась строка из восьми символов.

    // Видоизмененный способ шифрования и дешифрования сообщений
    // с помощью операции поразрядного исключающего ИЛИ.
    class Encode {
        public static void main(String args[]) {
            String msg = "This is a test";
            String encmsg = "";
            String decmsg = "";
            String key = "abcdefgi";
            int j;
            System.out.print("Original message: ");
            System.out.println(msg);
            // зашифровать сообщение
            j = 0;
            for(int i=0; i < msg.length(); i++) {
                encmsg = encmsg + (char) (msg.charAt(i) A key.charAt(j));
                j++;
                if(j==8) j = 0;
            }
            System.out.print("Encoded message: ");
            System.out.println(encmsg);
            // дешифровать сообщение
            j = 0;
            for(int i=0; i < msg.length(); i++) {
                decmsg = decmsg + (char) (encmsg.charAt(i) л key.charAt(j));
                j++;
                if(j==8) j = 0;
            }
            System.out.print("Decoded message: ");
            System.out.println(decmsg);
        }
    }
    
  8. Можно ли применять поразрядные операторы к значениям типа double? Нет, нельзя.

  9. Перепишите приведенную ниже последовательность операторов, воспользовавшись оператором ?.

    if(х < 0) у = 10;
    else у = 20;
    

    Ответ:

    у = х < 0 ? 10 : 20;
    
  10. В приведенном ниже фрагменте кода содержится знак &. Какой оператор он обозначает: поразрядный или логический? Обоснуйте свой ответ.

    boolean а, Ь;
    // ...
    if(a & b) ...
    

    Это логический оператор, поскольку оба его операнда относятся к типу boolean.

  11. Является ли ошибкой превышение верхней границы массива? Да.

    Является ли ошибкой использование отрицательных значений для доступа к элементам массива?

    Да. Значения индексов массива начинаются с нуля.

  12. Как обозначается оператор сдвига вправо без знака?

  13. Перепишите рассмотренный ранее в этой главе класс MinMax таким образом, чтобы в нем использовалась разновидность for-each цикла for.

    // Нахождение минимального и максимального значений в массиве,
    class MinMax {
        public static void main(String args[]) {
            int nums[] = new int[10];
            int min, max;
            nums[0] = 99;
            nums[l] = -10;
            nums[2] = 100123;
            nums[3] = 18;
            nums[4] = -978;
            nums[5] = 5623;
            nums[6] = 4 63;
            nums[7] = -9;
            nums[8] = 287;
            nums[9] = 4 9;
            min = max = nums[0];
            for(int v : nums) {
                if(v < min) min = v;
                if(v > max) max = v;
            }
            System.out.println("min and max: " + min + " " + max);
        }
    }
    
  14. В примере для опробования 5.1 была реализована пузырьковая сортировка. Можно ли в программе из этого примера заменить обычный цикл for его разновидностью for-each? Если нельзя, то почему? Циклы for, выполняющие сортировку в классе Bubble, нельзя преобразовать в вариант for-each. Что касается внешнего цикла, то текущее значение его переменной используется во внутреннем цикле. А что касается внутреннего цикла, то для перестановки следующих не по порядку элементов требуются операции присваивания значений элементам массива, чего нельзя добиться в варианте for-each.

  15. Можно ли управлять оператором switch с помощью объектов типа String? Можно, начиная с версии JDK 7.

Глава 6. Дополнительные сведения о методах и классах

  1. Допустим, имеется следующий фрагмент кода:
    class X {
        private int count;
    }
    
    Является ли допустимым приведенный ниже фрагмент кода?
    class Y {
        public static void main(String args[]) {
            X ob = new X();
            ob.count = 10;.
        }
    }
    
    Нет. Закрытый (private) член недоступен за пределами своего класса.
  2. Модификатор доступа должен _______ объявлению члена класса. предшествовать
  3. Помимо очереди, в программах часто используется структура данных, которая называется стеком. Обращение к стеку осуществляется по принципу “первым пришел — последним обслужен“. Стек можно сравнить со стопкой тарелок, стоящих на столе. Последней берется тарелка, поставленная на стол первой. Создайте класс Stack, реализующий стек для хранения символов. Используйте методы push () и pop () для манипулирования содержимым стека. Пользователь класса Stack должен иметь возможность задавать размер стека при его создании. Все члены класса Stack, кроме методов push () и pop (), должны быть объявлены как private. (Подсказка: в качестве заготовки можете воспользоваться классом Queue, изменив в нем лишь способ доступа к данным.)
    // Класс, реализующий стек для хранения символов,
    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];
            // скопировать элементы
            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++) {
                push(a[i]);
            }
        }
    
        // поместить символы в стек
        void push(char ch) {
            if(tos==stck.length) {
                System.out.println(" — Stack is full.");
                return;
            }
    
            stck[tos] = ch;
            tos++;
        }
    
        // извлечь символы из стека
        char pop() {
            if(tos==0) {
                System.out.println(" — Stack is empty.");
                return (char) 0;
            }
            tos—;
            return stck[tos];
        }
    }
    
    // продемонстрировать применение класса Stack
    class SDemo {
        public static void main(String args[]) {
            // создать пустой стек на 10 элементов
            Stack stkl = new Stack(lO);
            char name[] = {'T', 'o', 'm'};
            // построить стек из массива
            Stack stk2 = new Stack(name);
            char ch;
            int i;
            // поместить символы в стек stkl
            for(i=0; i < 10; i++)
                stkl.push((char) ('A' + i));
            // построить один стек из другого стека
            Stack stk3 = new Stack(stkl);
            // отобразить стеки
            System.out.print("Contents of stkl: ");
            for(i=0; i < 10; i++) {
                ch = stkl.pop();
                System.out.print(ch);
            }
            System.out.println("\n");
            System.out.print("Contents of stk2: ");
            for(i=0; i < 3; i++) {
                ch = stk2.pop();
                System.out.print(ch);
            }
            System.out.println("\n");
            System.out.print("Contents of stk3: ");
            for(i=0; i < 10; i++) {
                ch = stk3.pop();
                System.out.print(ch);
            }
        }
    }
    
    Ниже приведен результат выполнения данной программы.
    Contents of stkl: JIHGFEDCBA
    Contents of stk2: moT
    Contents of stk3: JIHGFEDCBA
    
  4. Допустим, имеется следующий класс:
    class Test {
        int a;
    
        Test(int i) { a = i; }
    }
    
    Напишите метод swap (), реализующий обмен содержимым между двумя объектами типа Test, на которые ссылаются две переменные данного типа.
    void swap(Test obi, Test ob2) {
        int t;
        t = obi.a;
        obi.a = ob2.a;
        ob2.a = t;
    }
    
  5. Правильно ли написан следующий фрагмент кода?
    class X {
    int meth(int a, int b) { ... }
    String meth(int a, int b) { ... }
    
    Нет, неправильно. Перегружаемые методы могут возвращать значения разного типа, но это не играет никакой роли для определения подобных методов во время их перегрузки. Перегружаемые методы должны иметь в своих списках разнотипные параметры.
  6. Напишите рекурсивный метод, отображающий строку задом наперед.
    // Отображение строки задом наперед с помощью рекурсии,
    class Backwards {
        String str;
        Backwards(String s) {
            str = s;
        }
    
        void backward(int idx) {
            if(idx != str.length()-1) backward(idx+1);
            System.out.print(str.charAt(idx) ) ;
        }
    }
    
    class BWDemo {
        public static void main(String args[]) {
            Backwards s = new Backwards("This is a test");
            s.backward(0);
        }
    }
    
  7. Допустим, что все объекты класса должны совместно пользоваться одной и той же переменной. Как объявить такую переменную? Переменная, предназначенная для совместного использования, должна быть объявлена как static.
  8. Для чего может понадобиться статический блок? Статический блок служит для выполнения любых инициализирующих действий в классе до создания конкретных объектов.
  9. Что такое внутренний класс? Внутренний класс — это нестатический вложенный класс.
  10. Допустим, требуется член класса, к которому могут обращаться только другие члены этого же класса. Какой модификатор доступа следует использовать в его объявлении? Модификатор доступа private.
  11. Имя метода и список его параметров вместе составляют ____________ метода. сигнатуру
  12. Если методу передается значение типа int, то в этом случае используется передача параметра по _______. значению
  13. Создайте метод sum () с аргументами переменной длины для суммирования передаваемых ему значений типа int. Метод должен возвращать результат суммирования. Продемонстрируйте его в действии. Существует много вариантов решения данной задачи. Ниже представлен один из них.
    class Sumlt {
        int sum(int ... n) {
            int result = 0;
            for(int i = 0; i < n.length; i++)
                result += n[i];
            return result;
        }
    }
    
    class SumDemo {
        public static Void main(String args[]) {
            Sumlt siObj = new Sumlt();
            int total = siObj.sum(l, 2, 3);
            System.out .println (1,Sum is " + total);
            total = siObj.sum(l, 2, 3, 4, 5);
            System.out.println("Sum is " + total);
        }
    }
    
  14. Можно ли перегружать метод с аргументами переменной длины? Да, можно.
  15. Приведите пример неоднозначного вызова перегружаемого метода с переменным числом аргументов. Ниже приведен один из вариантов перегружаемого метода с переменным числом аргументов, при вызове которого проявляется неоднозначность.
    double myMeth(double ... v ) { // ...
    double myMeth(double d, double ... v) { // ...
    
    Если попытаться вызвать метод myMeth () с одним аргументом следующим образом:
    myMeth(1.1);
    
    то компилятор не сможет определить, какой именно метод вызывается.

Глава 7. Наследование

  1. Имеет ли суперкласс доступ к членам подкласса? Имеет ли подкласс доступ к членам суперкласса? Нет, не имеет. Суперклассу ничего не известно о существовании подклассов. Подклассы действительно могут обращаться ко всем членам суперкласса, кроме тех, которые объявлены как закрытые (private).

  2. Создайте подкласс 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;
        }
    }
    
  3. Как предотвратить обращение к членам суперкласса из подкласса? Для того чтобы предотвратить доступ к членам суперкласса из подкласса, эти члены следует объявить как закрытые (private).

  4. Опишите назначение и два варианта использования ключевого слова super. Ключевое слово super используется в двух случаях. Во-первых, с его помощью вызывается конструктор суперкласса. В этом случае общая форма вызова имеет следующий вид:

    super (список_параметров) ;
    

    И во-вторых, это ключевое слово обеспечивает доступ к членам суперкласса. Ниже приведена общая форма такого доступа.

    super.член_класса
    
  5. Допустим, имеется следующая иерархия классов:

    class Alpha { ...
    class Beta extends Alpha { ...
    Class Gamma extends Beta { ...
    

    В каком порядке вызываются конструкторы этих классов при создании объекта класса Gamma?

    Конструкторы всегда вызываются в порядке наследования. Таким образом, при создании экземпляра класса Gamma будет сначала вызван конструктор Alpha, затем Beta и, наконец, Gamma.

  6. Переменная ссылки на суперкласс может указывать на объект подкласса. Объясните, почему это важно и как это связано с переопределением методов? Когда переопределяемый метод вызывается по ссылке на суперкласс, его вариант определяется по типу объекта, на который делается ссылка.

  7. Что такое абстрактный класс? Абстрактным называется такой класс, который содержит хотя бы один абстрактный метод.

  8. Как предотвратить переопределение метода? И как предотвратить наследование класса? Для того чтобы метод нельзя было переопределить, его нужно объявить как final. А для того чтобы предотвратить наследование от класса, его следует объявить как final.

  9. Объясните, каким образом механизмы наследования, переопределения методов и абстрактные классы используются для поддержки полиморфизма. Наследование, переопределение методов и абстрактные классы поддерживают полиморфизм и позволяют создать обобщенную структуру, реализуемую различными классами. Так, абстрактный класс определяет согласованный интерфейс, общий для всех реализующих его классов. Такой подход соответствует принципу “один интерфейс — множество методов”.

  10. Какой класс является суперклассом всех остальных классов? Класс Object.

  11. Класс, который содержит хотя бы один абстрактный метод, должен быть объявлен абстрактным. Верно или не верно? Верно.

  12. Какое ключевое слово следует использовать для создания именованной константы? Ключевое слово final.

Глава 8. Пакеты и интерфейсы

  1. Используя код, созданный в примере для опробования 8.1, поместите в пакет qpack интерфейс ICharQ и все три реализующие его класса. Класс IQDemo должен остаться в пакете, используемом по умолчанию. Покажите, как импортировать и использовать классы из пакета qpack. Для того чтобы включить интерфейс ICharQ и реализующие его классы в пакет qpack, следует поместить каждый из них в отдельный файл, объявить все классы, реализующие данный интерфейс, как public, а в начале каждого файла ввести следующий оператор:
    package qpack;
    
    После этого можно воспользоваться пакетом qpack, добавив в интерфейс IQDemo следующий оператор import:
    import qpack.*;
    
  2. Что такое пространство имен? Почему так важна возможность его разделения на отдельные области в Java? Пространство имен — это область объявлений. Разделяя пространство имен на отдельные области, можно предотвратить конфликты имен.
  3. Содержимое пакетов хранится в _______. каталогах
  4. В чем отличие доступа, определяемого ключевым словом protected, от доступа по умолчанию? Член класса с доступом типа protected может быть использован в пределах текущего пакета, а также в подклассах данного класса, относящихся к любому пакету. А член класса с доступом по умолчанию может быть использован только в пределах текущего пакета.
  5. Допустим, классы, содержащиеся в одном пакете, требуется использовать в другом пакете. Какими двумя способами можно этого добиться? Для того чтобы воспользоваться членом пакета, нужно указать его имя полностью или же импортировать этот член с помощью оператора import.
  6. “Один интерфейс — множество методов” — главный принцип Java. Какое языковое средство лучше всего демонстрирует этот принцип? Этот принцип объектно-ориентированного программирования лучше всего демонстрирует интерфейс.
  7. Сколько классов могут реализовать один и тот же интерфейс? Сколько интерфейсов может реализовать класс? Один интерфейс может быть реализован любым количеством классов. Класс может реализовать произвольное число интерфейсов.
  8. Может ли один интерфейс наследовать другой интерфейс? Да, может. Механизм наследования распространяется и на интерфейсы.
  9. Создайте интерфейс для класса 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);
    }
    
  10. Переменные, объявленные в интерфейсе, неявно считаются как static и final. Какие преимущества это дает? Переменные, объявленные в интерфейсе, могут служить в качестве именованных констант, общих для всех файлов программы. Доступ к ним обеспечивается путем импорта того интерфейса, в котором они объявлены.
  11. Пакет, по существу, является контейнером для классов. Верно или не верно? Верно.
  12. Какой стандартный пакет импортируется по умолчанию в любую программу на Java? Пакетт java.lang.

Глава 9. Обработка исключений

  1. Какой класс находится на вершине иерархии исключений? На вершине иерархии исключений находится класс Throwable.
  2. Объясните вкратце, как пользоваться ключевыми словами try и catch? Ключевые слова try и catch используются совместно. Операторы программы для отслеживания исключений помещаются в блок try. А перехват и обработка исключений осуществляются в блоке catch.
  3. Какая ошибка допущена в приведенном ниже фрагменте кода?
    // ...
    vals[18] = 10;
    catch (ArraylndexOutOfBoundsException exc) {
    // обработать ошибку
    }
    
    Блоку catch не предшествует блок try.
  4. Что произойдет, если исключение не будет перехвачено? Если исключение не будет перехвачено, произойдет аварийное завершение программы.
  5. Какая ошибка допущена в приведенном ниже фрагменте кода?
    class A extends Exception { ...
    class В extends А { ...
    // ...
    try {
    // ...
    }
    catch (A exc) { ... }
    catch (B exc) { ... }
    

В данном фрагменте кода оператор catch для суперкласса предшествует оператору catch для подкласса. А поскольку оператор catch для суперкласса может обработать также исключения, относящиеся к подклассу, то в программе окажется код, недоступный для выполнения. 6. Может ли внутренний блок catch повторно генерировать исключение, которое будет обработано во внешнем блоке catch? Да, исключения могут генерироваться повторно. 7. Блок finally — последний фрагмент кода, выполняемый перед завершением программы. Верно или неверно? Обоснуйте свой ответ. Неверно. Блок finally выполняется по завершении блока try. 8. Исключения какого типа необходимо явно объявлять с помощью оператора throws, включаемого в объявление метода? С помощью оператора throws объявляются все исключения, кроме RuntimeException и Error. 9. Какая ошибка допущена в приведенном ниже фрагменте кода? class MyClass { // ... } // ... throw new MyClass(); Класс MyClass не является производным от класса Throwable. С помощью оператора throw могут генерироваться лишь те исключения, которые являются подклассами, производными от класса Throwable. 10. Отвечая на вопрос 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];
        // скопировать элементы
        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];
    }
}
```
  1. Какими тремя способами можно сгенерировать исключение? Исключение может быть сгенерировано в результате ошибки в виртуальной машине Java, ошибки в программе или явным образом с помощью оператора throw.
  2. Назовите два подкласса, производных непосредственно от класса Throwable. Классы Error и Exception
  3. Что такое многократный перехват? Многократным называется такой перехват, который позволяет перехватывать два и больше исключений одним оператором catch.
  4. Следует ли перехватывать в программе исключения типа Error? Нет, не следует.

Глава 10. Ввод-вывод данных

  1. Для чего в Java определены как байтовые, так и символьные потоки? Байтовые потоки с самого начала были определены в Java. Они особенно удобны для ввода-вывода двоичных данных и поддерживают произвольный доступ к ним в файлах. А символьные потоки оптимизированы для представления в уникоде.
  2. Как известно, ввод-вывод данных на консоль осуществляется в текстовом виде. Почему же в Java для этой цели используются байтовые потоки? Стандартные потоки ввода-вывода System, in, System.out и System.err были определены в Java прежде символьных потоков.
  3. Как открыть файл для чтения байтов? Ниже приведен один из способов открытия файла для ввода данных типа byte.
    FilelnputStream fin = new FilelnputStream("test");
    
  4. Как открыть файл для чтения символов? Ниже приведен один из способов открытия файла для ввода символов.
    FileReader fr = new FileReader("test");
    
  5. Как открыть файл для ввода-вывода с произвольным доступом? Ниже приведен один из способов открытия файла для ввода-вывода с произвольным доступом.
    randfile = new RandomAccessFile("test", "rw");
    
  6. Как преобразовать числовую строку "123.23" в двоичный эквивалент? Для того чтобы преобразовать числовую строку в двоичный эквивалент, следует воспользоваться одним из методов синтаксического анализа, определенных в классах оболочек типов, например Integer или Double.
  7. Напишите программу, которая будет копировать текстовые файлы. Видоизмените ее таким образом, чтобы все пробелы заменялись дефисами. Используйте при написании программы классы, представляющие байтовые потоки, а также традиционный способ закрытия файла явным вызовом метода close ().
    /* Копирование текстового файла с заменой пробелов дефисами.
    
        В этой версии программы используются байтовые потоки.
    
        Для того чтобы воспользоваться этой программой, укажите
        в командной строке имена исходного и целевого файлов. Например:
        java Hyphen source target
    */
    import java.io.*;
    
    class Hyphen {
        public static void main(String args[])
        {
            int i;
            FilelnputStream fin = null;
            FileOutputStream fout = null;
    
            // проверить сначала, указаны ли оба файла
            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.close();
                } 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.");
                }
            }
        }
    }
    
  8. Перепишите программу, созданную в ответ на предыдущий вопрос, таким образом, чтобы в ней использовались классы, представляющие символьные потоки. На этот раз воспользуйтесь оператором 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);
            }
        }
    }
    
  9. К какому типу относится поток System.in? К типу InputStream.
  10. Что возвращает метод read () из класса InputStream по достижении конца потока? Значение -1.
  11. Поток какого типа используется для чтения двоичных данных? Поток типа DatalnputStream.
  12. Классы Reader и Writer находятся на вершине иерархии классов символьного ввода-вывода.
  13. Оператор try без ресурсов служит для _____. автоматического управления ресурсами
  14. Если для закрытия файла используется традиционный способ, то это лучше всего делать в блоке finally. Верно или неверно? Верно.

Глава 11. Многопоточное программирование

  1. Каким образом имеющиеся в Java средства многопоточного программирования позволяют писать более эффективные программы? Средства многопоточного программирования дают возможность использовать периоды простоя, наступающие практически в любой программе. Когда операции в одном потоке по каким-то причинам не выполняются, в действие вступают другие потоки. В многоядерных системах два и больше потоков могут исполняться одновременно.
  2. Для поддержки многопоточного программирования в Java предусмотрен класс и интерфейс . Для поддержки многопоточного программирования в Java предусмотрен класс Thread и интерфейс Runnable.
  3. В каких случаях следует отдать предпочтение расширению класса Thread над реализацией интерфейса Runnable? Подклассы, производные от класса Thread, целесообразно создавать в тех случаях, когда, помимо метода run (), требуется переопределить другие методы данного класса.
  4. Покажите, как с помощью метода j о in () можно организовать ожидание завершения потокового объекта MyThrd.
    MyThrd.join()
    
  5. Покажите, как установить приоритет потока MyThrd на три уровня выше нормального приоритета.
    MyThrd.setPriority(Thread.NORM_PRI0RITY+3);
    
  6. Что произойдет, если в объявлении метода указать ключевое слово synchronized? Если указать ключевое слово synchronized в объявлении метода, то в каждый момент времени этот метод будет вызываться только в одном потоке для любого заданного объекта его класса.
  7. Методы wait () и notify () служат для _____. взаимодействия потоков
  8. Внесите в класс TickTock изменения для организации настоящего отчета времени. Первую половину секунды должен занимать вывод на экран слова "Tick", а вторую — вывод слова "Tock". Таким образом, сообщение "Tick-Tock" должно соответствовать одной секунде отсчитываемого времени. (Время переключения контекстов можно не учитывать.) Для организации отчета времени достаточно ввести в классе TickTock вызовы метода sleep (), как показано ниже.
    // Вариант класса TickTock, в который введены вызовы
    // метода sleep() для организации отсчета времени.
    class TickTock {
        String state; // Состояние часов
    
        synchronized void tick(boolean running) {
            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"; // установить текущее состояние после такта "тик"
            notify(); // разрешить выполнение метода 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"; // установить текущее состояние после такта "так"
            notify(); // разрешить выполнение метода tick()
            try {
                while(!state.equals("ticked"))
                wait (); // ожидать завершения метода tick()
            }
            catch(InterruptedException exc) {
                System.out.println("Thread interrupted.");
            }
        }
    }
    
  9. Почему в новых программах на Java не следует применять методы suspend (), resume() и stop()? Методы suspend (), resume () и stop () не рекомендуется применять, поскольку они могут стать причиной серьезных осложнений при выполнении программы.
  10. С помощью какого метода из класса Thread можно получить имя потока? С помощью метода getName().
  11. Какое значение возвращает метод isAlive() ? Он возвращает логическое значение true, если вызывающий поток исполняется, или логическое значение false, если поток завершен.

Глава 12. Перечисления, автоупаковка, статический импорт и аннотации

  1. Константы перечислимого типа иногда называются самотипизированными. Что это означает? Часть “само” в термине самотипизированный означает тип перечисления, в котором определена константа. Следовательно, константа перечислимого типа является объектом того перечисления, в которое она входит.
  2. Какой класс автоматически наследуют перечисления? Все перечисления наследуют от класса Enum.
  3. Напишите для приведенного ниже перечисления программу, в которой метод 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');
        }
    }
    
  4. Программу, имитирующую автоматизированный светофор и созданную в примере для опробования 12.1, можно усовершенствовать, внеся ряд простых изменений, чтобы выгодно воспользоваться возможностями перечислений. В исходной версии этой программы продолжительность отображения каждого цвета светофора регулировалась в классе Traf ficLightSimulator, причем величины задержек были жестко запрограммированы в методе run (). Измените исходный код программы таким образом, чтобы продолжительность отображения каждого цвета светофора задавалась константами перечислимого типа 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();
        }
    
        // Запуск имитации  автоматизированного светофора.
        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 ();
        }
    }
    
  5. Что такое упаковка и распаковка? В каких случаях производится автоупаковка и автораспаковка? Упаковка означает включение значения простого типа в объект оболочки, а распаковка — извлечение значения из объекта оболочки. Автоупаковка означает автоматическую упаковку значения без явного создания объекта, тогда как при автораспаковке значение простого типа автоматически извлекается из объекта оболочки без явного вызова соответствующего метода, например intValue ().
  6. Измените следующий фрагмент кода таким образом, чтобы в нем производилась автоупаковка:
    Short val = new Short(123);
    
    Это задание имеет следующее решение:
    Short val = 123;
    
  7. Объясните, что такое статический импорт? Статический импорт означает размещение статических членов класса или интерфейса в глобальном пространстве имен. Это позволяет использовать статические члены без указания имени соответствующего класса или интерфейса.
  8. Какие действия выполняет приведенный ниже оператор?
    import static java.lang.Integer.parselnt;
    
    Этот оператор помещает в глобальное пространство имен метод parselnt () из класса оболочки типа Integer.
  9. Следует ли употреблять статический импорт от случая к случаю или желательно импортировать статические члены всех классов? Статический импорт уместен только в отдельных случаях. Если доступным окажется слишком много статических членов, это может привести к конфликтам имен и нарушению структуры кода.
  10. Синтаксис аннотации основывается на _____. интерфейсе
  11. Какая аннотация называется маркером? Маркер — это аннотация без аргументов.
  12. Аннотации применимы только к методам. Верно или неверно? Неверно. Любое объявление может быть аннотировано.

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

  1. Обобщения очень важны, поскольку они позволяют создавать код, который: а) обеспечивает типовую безопасность; б) пригоден для повторного использования; в) отличается высокой надежностью; г) обладает всеми перечисленными выше свойствами. Ответ: г) код обладает всеми перечисленными выше свойствами.
  2. Можно ли указывать простой тип в качестве аргумента типа? Нет, нельзя. В качестве аргументов типа можно указывать только типы объектов.
  3. Как объявить класс FlightSched с двумя параметрами типа? Это задание имеет следующее решение:
    class FlightSched<T, V> {
    
  4. Измените ваш ответ на вопрос 3 таким образом, чтобы второй параметр типа обозначал подкласс, производный от класса Thread. Это задание имеет следующее решение:
    class FlightSched<T, V extends Thread> {
    
  5. Внесите изменения в класс FlightSched таким образом, чтобы второй параметр типа стал подклассом первого параметра типа. Это задание имеет следующее решение:
    class FlightSchedCT, V extends Т> {
    
  6. Что обозначает знак ? в обобщениях? Знак ? обозначает метасимвольный аргумент, который соответствует любому допустимому типу.
  7. Может ли метасимвольный аргумент быть ограниченным? Да. Метасимвольный аргумент может ограничиваться как сверху, так и снизу.
  8. У обобщенного метода My Gen () имеется один параметр типа, определяющий тип передаваемого ему аргумента. Этот метод возвращает также объект, тип которого соответствует параметру типа. Как должен быть объявлен метод MyGen () ? Это задание имеет следующее решение:
    <Т> Т MyGen(Т о) {//.. .
    
  9. Допустим, обобщенный интерфейс объявлен так, как показано ниже,
    interface IGenlFCT, V extends Т> { // ...
    
    Составьте объявление класса MyClass, который реализует интерфейс IGenFCT. Это задание имеет следующее решение:
    class MyClass<T, V extends Т> implements IGenlFCT, V> { // ...
    
  10. Допустим, имеется обобщенный класс Counter. Как создать объект его базового типа? Для того чтобы получить базовый тип из обобщенного класса Counter, достаточно указать его имя, не обозначая тип, как показано ниже.
    Counter х = new Counter;
    
  11. Существуют ли параметры типа на стадии выполнения программы? Нет. Все параметры типа удаляются на стадии компиляции и заменяются соответствующими приводимыми типами. Этот процесс называется стиранием.
  12. Видоизмените ответ на вопрос 10 в упражнении по материалу главы 9 таким образом, чтобы сделать класс обобщенным. По ходу дела создайте интерфейс стека IGenStack, объявив в нем обобщенные методы push () и pop ().
    // Обобщенный стек.
    interface IGenStack<T> {
        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<T> implements IGenStack<T> {
        private T stck[]; // Массив для хранения элементов стека
        private int tos; // Вершина стека
    
        // построить пустой стек заданного размера
        GenStack(T[] stckArray) {
            stck = stckArray;
            tos = 0;
        }
    
        // построить один стек из другого стека
        GenStack(T[] stckArray, GenStack<T> ob) {
            tos = ob.tos;
            stck = stckArray;
            try {
            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<Integer> stkl = new GenStack<Integer> (i'Store) ;
            // построить стек из массива
            String name[] = {"One", "Two", "Three"};
            String strStore[] = new String[3];
            GenStack<String> stk2 =
            new GenStack<String>(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<String> stk3 =
            new GenStack<String>(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();
        }
    }
    
  13. Что обозначают угловые скобки (< >)? Угловые скобки обозначают ромбовидный оператор.
  14. Как упростить приведенную ниже строку кода в версии JDK 7? `` MyClass<Double,String> obj = new MyClass<Double,String>(1.1,"Hi");
    Эту строку кода можно упростить, используя ромбовидный оператор следующим образом:
    
    MyClass<Double,String> obj = new MyClasso(1.1,"Hi");
    
    

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

  1. Какой метод вызывается первым в начале выполнения апплета? Какой метод вызывается, когда апплет должен быть удален из системы? Выполнение апплета начинается с вызова метода init (). А перед удалением апплета вызывается метод destroy ()..
  2. Почему в апплете, который должен работать постоянно, следует организовать многопоточный режим? Многопоточный режим необходим в постоянно выполняющемся апплете, потому что апплет — это управляемая событиями прикладная программа, в которой не предусмотрены длительные операции. Например, метод paint () не будет вызван до тех пор, пока метод start () не возвратит управление.
  3. Видоизмените апплет, созданный в примере для опробования 14.1, таким образом, чтобы в нем отображалась символьная строка, передаваемая ему в качестве параметра. Добавьте еще один параметр, чтобы задавать время задержки (в миллисекундах) между последовательными сдвигами символов строки.
    /* Простой апплет, отображающий крупный
    заголовок с использованием параметров.
    */
    import java.awt.*;
    import java.applet.*;
    /*
    <applet code="ParamBanner" width=300 height=50>
    <param name=message value=" I like Java! ">
    <param name=delay value=500>
    </applet>
    */
    public class ParamBanner extends Applet implements Runnable {
        String msg;
        int delay;
        Thread t;
        boolean stopFlag;
    
        // инициализировать переменную t пустым значением null
        public void init() {
            String temp;
            msg = getParameter("message");
            if(msg == null) msg = " Java Rules the Web ";
            temp = getParameter("delay");
            try {
                if(temp != null)
                delay = Integer.parselnt(temp);
                else
                delay =250; // Если параметр не задан,
                // используется значение по умолчанию.
            } catch(NumberFormatException exc) {
                delay = 250 ; // Если допущена ошибка, используется
                // значение по умолчанию.
            }
            t = null;
        }
    
        // запустить поток
        public void start() {
            t = new Thread(this);
            stopFlag = false;
            t.start();
        }
    
        // Точка входа в поток, манипулирующий крупным заголовком,
        public void run() {
            char ch;
            // отобразить крупный заголовок снова
            for( ; ; ) {
                try {
                    repaint();
                    Thread.sleep(delay); *
                    ch = msg.charAt(0);
                    msg = msg.substring(1, msg.length());
                    msg += ch;
                    if (stopFlag)
                        break;
                } catch(InterruptedException exc) {}
            }
        }
    
        // остановить отображение крупного заголовка
        public void stop() {
            stopFlag = true;
            t = null;
        }
    
        // отобразить крупный заголовок
        public void paint(Graphics g) {
            g.drawString(msg, 50, 30);
        }
    }
    
  4. Дополнительное задание. Создайте апплет, который отображал бы текущее время, обновляя содержимое своего окна каждую секунду. Для того чтобы справиться с этим заданием, вам придется провести дополнительные изыскания. Для начала примите к сведению следующую подсказку: получить текущее время можно, воспользовавшись объектом класса Calendar, относящегося к пакету java.util. (Напомним, что компания Oracle предоставляет оперативно доступную документацию на все стандартные классы Java.) Приобретенных вами до сих пор знаний должно быть достаточно для того, чтобы самостоятельно изучить класс Calendar и использовать его методы для выполнения этого задания.
    // Простой апплет, отображающий текущее время.
    import java.util.*;
    import java.awt.*;
    import java.applet.*;
    /*
    <object code="Clock" width=200 height=50>
    </object>
    */
    public class Clock extends Applet implements Runnable {
        String msg;
        Thread t;
        Calendar clock;
        boolean stopFlag;
    
        // инициализировать апплет
        public void init() {
            t = null;
            msg = null;
        }
    
        // запустить поток
        public void start() {
            t = new Thread(this);
            stopFlag = false;
            t.start();
        }
    
        // Точка входа в поток, отображающий время,
        public void run ()  {
            // отобразить время повторно
            for( ; ; )  {
            try {
                repaint();
                Thread.sleep(1000);
                if(stopFlag)
                    break;
            } catch(InterruptedException exc) {}
            }
        }
    
        // приостановить поток, отображающий время
        public void stop () {
            stopFlag = true;
            t = null;
        }
    
        // отобразить время
        public void paint(Graphics g) {
            clock = Calendar.getlnstance();
            msg = "Current time is " +
                    Integer.toString(clock.get(Calendar.HOUR));
            msg = msg + ":" +
                Integer.toString(clock.get(Calendar.MINUTE));
            msg = msg + ":" +
                Integer.toString(clock.get(Calendar.SECOND));
            g.drawString(msg, 30, 30);}
        }
    }
    
  5. Поясните вкратце, каким образом действует модель делегирования событий в Java. В модели делегирования событий источник формирует событие и передает его одному или нескольким приемникам, которые лишь ожидают наступления события. Получив уведомление, приемник обрабатывает событие, а затем возвращает управление.
  6. Должен ли приемник событий быть зарегистрирован в их источнике? Должен. Для того чтобы приемник получал уведомления о событиях, он должен быть зарегистрирован в источнике.
  7. Дополнительное задание. Среди языковых средств Java для отображения информации имеется метод drawLine (). Он рисует текущим цветом прямую линию между двумя точками. Этот метод относится классу Graphics. Используя метод drawLine (), напишите апплет, отслеживающий перемещение мыши. Если кнопка мыши нажата, апплет должен рисовать на экране непрерывную линию до тех пор, пока кнопка не будет отпущена.
    /* Отслеживание перемещения мыши путем рисования линии.
    Признаками начала и конца линии являются нажатие
    и отпускание кнопки мыши. */
    import java.awt.*;
    import java.awt.event.*;
    import java.applet.*;
    /*
    <applet code="TrackM" width=300 height=100>
    </applet>
    */
    public class TrackM extends Applet
        implements MouseListener, MouseMotionListener {
        int curX = 0, curY =0; // Текущие координаты
        int oldX = 0, oldY =0; // Предыдущие координаты
        boolean draw;
    
        public void init () {
            addMouseListener(this);
            addMouseMotionListener(this);
            draw = false;
        }
    
        /* Следующие три метода не используются, но их пустые реализации
        нужны, так как эти методы объявлены в интерфейсе MouseListener. */
    
        // обработать наведение курсора мыши на элемент
        // пользовательского интерфейса
        public void mouseEntered(MouseEvent me) {
        }
    
        // обработать отведение мыши от элемента
        // пользовательского интерфейса
        public void mouseExited(MouseEvent me) {
        }
    
        // обработать щелчок кнопкой мыши
        public void mouseClicked(MouseEvent me) {
        }
    
        // обработать нажатие кнопки мыши
        public void mousePressed(MouseEvent me) {
            // сохранить координаты
            oldX = me.getx();
            oldY = me.getY();
            draw = true;
        }
    
        // обработать отпускание кнопки мыши
        public void mouseReleased(MouseEvent me) {
            draw = false;
        }
    
        // обработать перетаскивание мыши
        public void mouseDragged(MouseEvent me) {
            // сохранить координаты
            curX = me.getx();
            curY = me.getY();
            repaint();
        }
    
        // обработать перемещение мыши
        public void mouseMoved(MouseEvent me) {
            // отобразить состояние
            showStatus ("Moving mouse at " + me.getXO + ", " + me.getYO);
        }
    
        // отобразить линию в окне апплета
        public void paint(Graphics g) {
            if(draw)
                g.drawLine(oldX, oldY, curX, curY);
        }
    }
    
  8. Объясните назначение ключевого слова assert. Ключевое слово assert создает утверждение, т.е. условие, которое должно быть истинным при выполнении программы. Если же утверждение ложно, генерируется исключение AssertionError.
  9. Приведите хотя бы одну причину, по которой может возникнуть потребность в использовании собственного метода в некоторых программах. Собственный метод может понадобиться для сопряжения с подпрограммами, написанными на других языках программирования, или для оптимизации кода с учетом конкретной среды исполнения.

Глава 15. Введение в Swing

  1. Компоненты AWT являются тяжеловесными, а компоненты Swing — легковесными
  2. Может ли изменяться стиль оформления компонента Swing? Если да, то какое средство позволяет это сделать? Да, может. Это позволяют сделать подключаемые стили оформления в Swing.
  3. Какой контейнер верхнего уровня чаще всего используется в приложениях? Контейнер JFrame.
  4. Контейнер верхнего уровня содержит несколько панелей. На какой панели размещаются компоненты? На панели содержимого.
  5. Как создать ссылку, отображающую сообщение "Select an entry from the list" (Выберите элемент из списка)?
    JLabel("Select an entry from the list")
    
  6. В каком потоке должно происходить все взаимодействие с компонентами графического пользовательского интерфейса? В потоке диспетчеризации событий.
  7. Какая команда действия связывается по умолчанию с компонентом JButton? Как изменить команду действия? По умолчанию символьная строка команды действия содержит текст надписи на кнопке. Команду действия можно изменить, вызвав метод setActionCommand ().
  8. Какое событие формируется при нажатии кнопки? Событие ActionEvent.
  9. Как создать поле ввода текста шириной до 32 символов?
    JTextField(32)
    
  10. Можно ли установить команду действия для компонента JTextField? Если можно, то как это сделать? Да, можно. Для этого достаточно вызвать метод setActionCommand ().
  11. С помощью какого компонента Swing можно создать флажок? Какое событие формируется при установке или сбросе флажка? Флажок создается с помощью компонента JCheckBox. При установке или сбросе флажка формируется событие ItemEvent.
  12. Компонент JList отображает список элементов, которые может выбирать пользователь. Верно или неверно? Верно.
  13. Какое событие формируется при выборе пользователем элемента из списка типа JList или отмене выбора? Событие ListSelectionEvent.
  14. В каком методе задается режим выбора элементов списка типа JList? С помощью какого метода можно получить индекс первого выбранного элемента? Режим выбора элементов списка задается в методе setSelectionMode (). А метод getSelectedlndex () возвращает индекс первого выбранного элемента.
  15. Подкласс какого класса нужно создать при разработке Swing-апплета? Подкласс JApplet.
  16. Обычно при построении исходного пользовательского интерфейса в Swing-апплетах используется метод invokeAndWait (). Верно или неверно? Верно.
  17. Добавьте в утилиту сравнения файлов, созданную в примере для опробования 15.1, флажок со следующей пояснительной надписью: Show position of mismatch (Показывать место несовпадения). Если этот флажок установлен, программа должна отображать место, в котором обнаружено первое расхождение в содержимом сравниваемых файлов.
    /*
    Пример для опробования 15-1.
    Утилита сравнения файлов, создаваемая на основе Swing.
    В этой версии присутствует флажок для установки режима показа
    места первого несовпадения содержимого сравниваемых файлов.
    Для компиляции этой утилиты требуется JDK 7
    или более поздняя версия данного комплекта.
    */
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.io.*;
    class SwingFC implements ActionListener {
        JTextField jtfFirst; // Переменная для хранения имени первого файла
        JTextField jtfSecond; // Переменная для хранения имени второго файла
        JButton jbtnComp; // Кнопка для сравнения файлов
        JLabel jlabFirst, jlabSecond; // Подсказки для пользователя
        JLabel jlabResult; // Сведения о результатах и сообщения об ошибках
        JCheckBox jcbLoc; // флажок для показа места первого несовпадения файлов
    
        SwingFC () {
            // создать новый контейнер JFrame
            JFrame jfrm = new JFrame("Compare Files");
            // установить диспетчер компоновки FlowLayout
            jfrm.setLayout(new FlowLayout());
            // задать исходные размеры рамки окна
            jfrm.setSize(200, 190);
            // завершить программу после закрытия окна
            jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            // создать поля для ввода имен файлов
            jtfFirst = new JTextField(14);
            jtfSecond = new JTextField(14);
            // установить команды действия для полей ввода текста
            jtfFirst.setActionCommand("fileA");
            jtfSecond.setActionCommand("fileB");
            // создать кнопку Compare
            JButton jbtnComp = new JButton("Compare");
            // добавить приемник событий действия от кнопки Compare
            jbtnComp.addActionListener(this) ;
            // создать метки
            jlabFirst = new JLabel("First file: ");
            jlabSecond = new JLabel("Second file: ");
            jlabResult = new JLabel("");
            // создать флажок
            jcbLoc = new JCheckBox("Show position of mismatch");
            // добавить компоненты на панели содержимого
            jfrm.add(jlabFirst);
            jfrm.add(jtfFirst) ;
            jfrm.add(jlabSecond) ;
            jfrm.add(jtfSecond);
    
            jfrm.add(j cbLoc);
            Приложение А. Ответы на вопросы для самопроверки 599.
            jfrm.add(jbtnComp);
            jfrm.add(jlabResult);
    
            // отобразить рамку окна
            j frm.setVisible(true);
        }
    
        // сравнить файлы после нажатия кнопки Compare
        public void actionPerformed(ActionEvent ae) {
            int i=0, j=0;
            // сначала убедиться, что введены имена обоих файлов
            if(jtfFirst.getText().equals("")) {
                jlabResult.setText("First file name missing.");
                return;
            }
    
            if(jtfSecond.getText().equals("")) {
                jlabResult.setText("Second file name missing.");
                return;
            }
    
            // сравнить файлы, используя оператор try с ресурсами
            try (FilelnputStream    fl  =   new FilelnputStream(jtfFirst.getText());
            FilelnputStream f2  =   new FilelnputStream(jtfSecond.getText()))
            {
                // проверить содержимое каждого файла
                do {
                    i = f1.read();
                    j = f2.read();
                    if(i != j) break;
                }   whiled != -1 && j !=    -1) ;
                if(i != j) {
                    if(jcbLoc.isSelected())
                        jlabResult.setText("Files differ at location " + count);
                    else
                        jlabResult.setText("Files are not the same.");
                }
                else
                    jlabResult.setText("Files compare equal.");
            } catch(IOException exc) {
                jlabResult.setText("File Error");
            }
        }
    
        public static void main(String args[]) {
            // создать рамку окна в потоке диспетчеризации событий
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new SwingFC();
                }
            });
        }
    }
    
  18. Измените программу List Demo таким образом, чтобы она допускала выбор нескольких элементов из списка.
    // Демонстрация выбора нескольких элементов из списка
    // с помощью компонента Jlist.
    // Для компиляции этой программы требуется JDK 7
    // или более поздняя версия данного комплекта.
    import javax.swing.*;
    import javax.swing.event;
    import java.awt.*;
    import java.awt.event.*;
    
    class ListDemo implements ListSelectionListener {
        JList<String> jlst;
        JLabel jlab;
        JScrollPane jscrlp;
        // создать массив имен
        String names[] = { "Sherry", "Jon", "Rachel",
                           "Sasha", "Josselyn", "Randy",
                           "Tom", "Mary", "Ken",
                           "Andrew", "Matt", "Todd" };
    
        ListDemo()  {
            // создать новый контейнер JFrame
            JFrame jfrm = new JFrame("JList Demo");
            // установить диспетчер компоновки FlowLayout
            jfrm.setLayout(new FlowLayout());
    
            // задать исходные размеры рамки окна
            jfrm.setSize(200, 160);
    
            // завершить программу после закрытия окна
            jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            // создать компонент JList
            jlst = new JList<String>(names);
    
            // Удалив следующую строку кода, можно задать режим выбора
            // нескольких элементов из списка, поскольку этот режим
            // устанавливается для компонента JList по умолчанию.
            // jlst.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            // добавить список на панели прокрутки,
            jscrlp = new JScrollPane(jlst);
    
            // задать предпочтительные размеры панели прокрутки
            jscrlp.setPreferredSize(new Dimension(120, 90));
    
            // создать метку для отображения результатов выбора из списка,
            jlab = new JLabel("Please choose a name");
    
            // добавить обработчик событий, связанных с выбором из списка
            jlst.addListSelectionListener(this);
    
            // добавить список и метку на панели содержимого
            jfrm.add(jscrip);
            jfrm.add(jlab);
    
            // отобразить рамку окна
            jfrm.setVisible(true);
        }
    
        // обработать события, связанные с выбором элементов из списка
        public void valueChanged(ListSelectionEvent le) {
            // получить индексы тех элементов, выбор которых был сделан
            // или отменен в списке
            int indices[] = j1st.getSelectedlndices();
            // отобразить результат выбора, если был выбран один
            // или несколько элементов из списка
            if(indices.length != 0) {
                String who = "";
                // построить символьную строку из выбранных имен
                for(int i : indices)
                    who += names[i] + " ";
                jlab.setText("Current selections: " + who);
            }
            else // иначе еще раз предложить сделать выбор
                jlab.setText("Please choose a name");
        }
    
        public static void main(String args[]) {
            // создать рамку окна в потоке диспетчеризации событий
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new ListDemo();
                }
            });
        }
    }