
- •Кен Арнольд Джеймс Гослинг Дэвид Холмс Язык программирования Java
- •Глава 1 первое знакомство с java 6
- •Глава 2 классы и объекты 29
- •Глава 3 расширение классов 47
- •Глава 4 интерфейсы 70
- •Глава 5 лексемы, операторы и выражения 78
- •Глава 6 порядок выполнения 105
- •Глава 7 исключения 113
- •Глава 8 строки 121
- •Глава 9 потоки 134
- •Глава 10 пакеты 156
- •Глава 11 пакет ввода/вывода 158
- •Глава 12 стандартные вспомогательные средства 183
- •Глава 13 применение типов в программировании 205
- •Глава 14 системное программирование 218
- •Глава1 первое знакомство сjava
- •1.1. С самого начала
- •1.2.Переменные
- •1.3. Комментарии
- •1.4.Именованные константы
- •1.4.1. Символы Unicode
- •1.5.Порядок выполнения
- •1.6.Классы и объекты
- •1.6.1.Создание объектов
- •1.6.2.Статические поля
- •1.6.3.Сборщик мусора
- •1.7.Методы и параметры
- •1.7.1.Вызов метода
- •1.7.2.Ссылка this
- •1.7.3.Статические методы
- •1.8.Массивы
- •1.9.Строковые объекты
- •1.10.Расширение класса
- •1.10.1.Класс Object
- •1.10.2.Вызов методов суперкласса
- •1.11. Интерфейсы
- •1.12.Исключения
- •1.13.Пакеты
- •1.14.Инфраструктура Java
- •1.15.Прочее
- •Глава 2 классы и объекты
- •2.1. Простой класс
- •2.2. Поля
- •2.3. Управление доступом и наследование
- •2.4. Создание объектов
- •2.5. Конструкторы
- •2.6. Методы
- •2.6.1. Значения параметров
- •2.6.2. Применение методов для ограничения доступа
- •2.7. Ссылка this
- •2.8. Перегрузка методов
- •2.9. Статические члены
- •2.9.1. Блоки статической инициализации
- •2.9.2. Статические методы
- •2.10. Сборка мусора и метод finalize
- •2.10.1. Метод finalize
- •2.10.2. Восстановление объектов в методе
- •2.11. Метод main
- •2.12. Метод toString
- •2.13. Родные методы
- •Глава 3 расширение классов
- •3.1. Расширенный класс
- •3.2. Истинное значение protected
- •3.3. Конструкторы в расширенных классах
- •3.3.1. Порядок вызова конструкторов
- •3.4. Переопределение методов и скрытие полей
- •3.4.1. Ключевое слово super
- •3.5. Объявление методов и классов с ключевым словом final
- •3.6. Класс Object
- •3.7. Абстрактные классы и методы
- •3.8. Дублирование объектов
- •3.9. Расширение классов: когда и как
- •3.10. Проектирование расширяемого класса
- •Глава 4 интерфейсы
- •4.1. Пример интерфейса
- •4.2. Одиночное и множественное наследование
- •4.3. Расширение интерфейсов
- •4.3.1. Конфликты имен
- •4.4. Реализация интерфейсов
- •4.5. Использование реализации интерфейса
- •4.6. Для чего применяются интерфейсы
- •Глава 5 лексемы, операторы и выражения
- •5.1. Набор символов
- •5.2. Комментарии
- •5.3. Лексемы
- •5.4. Идентификаторы
- •5.4.1. Зарезервированные слова Java
- •5.5. Примитивные типы
- •5.6. Литералы
- •5.6.1. Ссылки на объекты
- •5.6.2. Логические значения
- •5.6.3. Целые значения
- •5.6.4. Значения с плавающей точкой
- •5.6.5. Символы
- •5.6.6. Строки
- •5.7. Объявления переменных
- •5.7.1. Значение имени
- •5.8. Массивы
- •5.8.1. Многомерные массивы
- •5.9. Инициализация
- •5.9.1. Инициализация массивов
- •5.10. Приоритет и ассоциативность операторов
- •5.11. Порядок вычислений
- •5.12. Тип выражения
- •5.13. Приведение типов
- •5.13.1. Неявное приведение типов
- •5.13.2. Явное приведение и instanceof
- •5.13.3. Строковое приведение
- •5.14. Доступ к членам
- •5.15. Арифметические операторы
- •5.15.1. Целочисленная арифметика
- •5.15.2. Арифметика с плавающей точкой
- •5.15.3. Арифметика с плавающей точкой и стандарт ieee-754
- •5.15.4. Конкатенация строк
- •5.16. Операторы приращения и уменьшения
- •5.17. Операторы отношения и условный оператор
- •5.18. Поразрядные операции
- •5.19. Условный оператор
- •5.20. Операторы присваивания
- •5.21. Имена пакетов
- •Глава 6 порядок выполнения
- •6.1. Операторы и блоки
- •6.2. Оператор if-else
- •6.3. Оператор switch
- •6.4. Цикл while и do-while
- •6.5. Оператор for
- •6.6. Метки
- •6.7. Оператор break
- •6.8. Оператор continue
- •6.9. Оператор return
- •Глава 7 исключения
- •7.1. Создание новых типов исключений
- •7.2. Оператор throw
- •7.3. Условие throws
- •7.4. Операторы try, catch и finally
- •7.4.1. Условие finally
- •7.5. Когда применяются исключения
- •Глава 8 строки
- •8.1. Основные операции со строками
- •8.2. Сравнение строк
- •8.3. Вспомогательные методы
- •8.4. Создание производных строк
- •8.5. Преобразование строк
- •8.6. Строки и символьные массивы
- •8.7. Строки и массивы byte
- •8.8. Класс StringBuffer
- •8.8.1. Модификация буфера
- •8.8.2. Извлечение данных
- •8.8.3. Работа с емкостью буфера
- •Глава 9 потоки
- •9.1. Создание потоков
- •9.2. Синхронизация
- •9.2.1. Методы synchronized
- •9.2.2. Операторы synchronized
- •9.3. Методы wait и notify
- •9.4. Подробности, касающиеся wait и notify
- •9.5. Планирование потоков
- •9.6. Взаимная блокировка
- •9.7. Приостановка потоков
- •9.8. Прерывание потока
- •9.9. Завершение работы потока
- •9.10. Завершение приложения
- •9.11. Использование Runnable
- •9.12. Ключевое слово volatile
- •9.13. Безопасность потоков и ThreadGroup
- •9.14. Отладка потоков
- •Глава 10 пакеты
- •10.1. Имена пакетов
- •10.2. Пакетный доступ
- •10.3. Содержимое пакета
- •Глава 11 пакет ввода/вывода
- •11.1. Потоки
- •11.2. Класс InputStream
- •11.3. Класс OutputStream
- •11.4. Стандартные типы потоков
- •11.5. Фильтрующие потоки
- •11.6. Класс PrintStream
- •11.7. Буферизованные потоки
- •11.8. Байтовые потоки
- •11.9. Класс StringBufferInputStream
- •11.10. Файловые потоки и FileDescriptor
- •11.11. Конвейерные потоки
- •11.12. Класс Seq uenceInputStream
- •11.13. Класс LineNumberInputStream
- •11.14. Класс PushbackInputStream
- •11.15. Класс StreamTokenizer
- •11.16. Потоки данных
- •11.16.1. Классы потоков данных
- •11.17. Класс RandomAccessFile
- •11.18. Класс File
- •11.19. Интерфейс FilenameFilter
- •11.20. Классы ioException
- •Глава 12 стандартные вспомогательные средства
- •12.1. Класс BitSet
- •12.2. Интерфейс Enumeration
- •12.3. Реализация интерфейса Enumeration
- •12.4. Класс Vector
- •12.5. Класс Stack
- •12.6. Класс Dictionary
- •12.7. Класс Hashtable
- •12.8. Класс Properties
- •12.9. Классы Observer/Observable
- •12.10. Класс Date
- •12.11. Класс Random
- •12.12. Класс String Tokenizer
- •Глава 13 применение типов в программировании
- •13.1. Класс Class
- •13.2. Загрузка классов
- •13.3. Классы-оболочки: общий обзор
- •13.4. Класс Boolean
- •13.5. Класс Character
- •13.6. Класс Number
- •13.7. Класс Integer
- •13.8. Класс Long
- •13.9. Классы Float и Double
- •Глава 14 системное программирование
- •14.1. Стандартный поток ввода/вывода
- •14.2. Управление памятью
- •14.3. Системные свойства
- •14.4. Создание процессов
- •14.5. Класс Runtime
- •14.6. Разное
- •14.7. Безопасность
- •14.8. Класс Math
- •Приложение а Родные методы
- •А.1 Обзор
- •А.2.1 Имена
- •А.2.2 Методы
- •А.2.3 Типы
- •А.2.5 Средства безопасности
- •А.2.6 Работа с памятью
- •А.3 Пример
- •А.3.1 Внутреннее строение LockableFile
- •А.4 Строки
- •А.5 Массивы
- •А.6 Создание объектов
- •А.7 Вызов методов Java
- •А.8 Последнее предупреждение
- •Приложение б Runtime-исключения в Java
- •Б.1 Классы RuntimeException
- •Б.2 Классы Error
- •Приложение в Полезные таблицы
1.8.Массивы
Простые переменные, содержащие всего одно значение, полезны, но для многих приложений их недостаточно. Скажем, для разработки программы игры в карты требуется множество объектов Card, с которыми можно было бы оперировать как с единым целым. Для таких случаев в языке Java предусмотрены массивы.
Массивом называется набор переменных, относящихся к одному типу. Доступ к элементам массива осуществляется посредством простых целочисленных индексов. В карточной игре объект Deck (колода) может выглядеть так:
class Deck {
final int DECK_SIZE = 52;
Card[] cards = new Card[DECK_SIZE];
public void print() {
for (int i = 0; i < cards.length; i++)
System.out.println(cards[i]);
}
}
Сначала мы объявляем константу с именем DECK_SIZE, содержащую количество кард в колоде. Затем поле cards объявляется в виде массива типа Card— для этого после имени типа в объявлении необходимо поставить квадратные скобки [ и ]. Размер массива определяется при его создании и не может быть изменен в будущем.
Вызов метода print показывает, как производится доступ к элементам массива: индекс нужного элемента заключается в квадратные скобки [ и ], следующие за именем массива.
Как нетрудно догадаться по тексту программы, в объекте-массиве имеется поле length, в котором хранится количество элементов в массиве. Границами массива являются целые числа 0 и length-1. Если попытаться обратиться к элементу массива, индекс которого выходит за эти пределы, то возбуждается исключение IndexOutOfBounds.
В этом примере также демонстрируется новый механизм объявления переменных— переменная цикла объявлена в секции инициализации цикла for. Объявление переменной в секции инициализации— удобный и наглядный способ объявления простой переменной цикла. Такая конструкция допускается лишь при инициализации цикла for; вы не сможете объявить переменную при проверке условия в операторе if или while.
Переменная цикла i существует лишь внутри оператора for. Переменная цикла, объявленная подобным образом, исчезает сразу же после его завершения— это означает, что ее имя может использоваться в качестве имени переменной в последующих операторах цикла.
Упражнение 1.8
Измените приложение Fibonacci так, чтобы найденные числа Фибоначчи сохранялись в массиве и выводились в виде списка значений в конце программы.
Упражнение 1.9
Измените приложение Fibonacci так, чтобы числа Фибоначчи сохранялись в массиве. Для этого создайте новый класс для хранения самого числа и логического значения, являющегося признаком четности, после чего создайте массив для ссылок на объекты этого класса.
1.9.Строковые объекты
Для работы с последовательностями символов в Java предусмотрены тип объектов String и языковая поддержка при их инициализации. Класс String предоставляет разнообразные методы для работы с объектами String.
Примеры литералов типа String уже встречались нам в примерах— в частности, в программе HelloWorld. Когда в программе появляется оператор следующего вида:
System.out.println(“Hello, world”);
компилятор Java на самом деле создает объект String, присваивает ему значение указанного литерала и передает его в качестве параметра методу println.
Объекты типа String отличаются от массивов тем, что при их создании не нужно указывать размер. Создание нового объекта String и его инициализация выполняются всего одним оператором, как показывает следующий пример:
class StringDemo {
static public void main(String args[]) {
String myName = “Petronius”;
myName = myName + “ Arbiter”;
System.out.println(“Name = ” + myName);
}
}
Мы создаем объект String с именем myName и инициализируем его строковым литералом. Выражение с оператором конкатенации +, следующее за инициализацией, создает новый объект String с новым значением. Наконец, значение myName выводится в стандартный выходной поток. Результат работы приведенной выше программы будет таким:
Name = Petronius Arbiter
Кроме знака +, в качестве оператора конкатенации можно использовать оператор += как сокращенную форму, в которой название переменной размещается в левой части оператора. Усовершенствованная версия приведенного выше примера выглядит так:
class BetterStringDemo {
static public void main(String args[]) {
String myName = “Petronius”;
String occupation = “Reorganization Specialist”;
myName = myName + “ Arbiter”;
myName += “ ”;
myName += “(” + occupation + “)”;
System.out.println(“Name = ” + myName);
}
}
Теперь при запуске программы будет выведена следующая строка:
Name = Petronius Arbiter (Reorganization Specialist)
Объекты String содержат метод length, который возвращает количество символов в строке. Символы имеют индексы от 0 до length()-1.
Объекты String являются неизменяемыми, или доступными только для чтения; содержимое объекта String никогда не меняется. Когда в программе встречаются операторы следующего вида:
str = “redwood”;
// ... сделать что-нибудь со str ...
str = “oak”;
второй оператор присваивания задает новое значение ссылки на объект, а не содержимого строки. При каждом выполнении операции, которая на первый взгляд изменяет содержимое объекта (например, использование выше +=), на самом деле возникает новый объект String, также доступный только для чтения,— тогда как содержимое исходного объекта String остается неизменным. Класс StringBuffer позволяет создавать строки с изменяющимся содержимым; этот класс описывается в главе 8, в которой подробно рассматривается и класс String.
Самый простой способ сравнить два объекта String и выяснить, совпадает ли их содержимое, заключается в использовании метода equals:
if (oneStr.equals(twoStr))
foundDuplicate(oneStr, twoStr);
Другие методы, в которых сравниваются части строки или игнорируется регистр символов, также рассматриваются в главе8.
Упражнение 1.10
Измените приложение StringsDemo так, чтобы в нем использовались разные строки.
Упражнение 1.11
Измените приложение ImprovedFibonacci так, чтобы создаваемые в нем объекты String сначала сохранялись в массиве, а не выводились бы сразу же на печать методом println.