
- •Кен Арнольд Джеймс Гослинг Дэвид Холмс Язык программирования 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
- •Приложение в Полезные таблицы
3.6. Класс Object
Все классы являются явными или неявными расширениями класса Object и, таким образом, наследуют его методы. Последние делятся на две категории: общие служебные и методы, поддерживающие потоки. Работа с потоками рассматривается в главе 9. В этом разделе описываются служебные методы Object и их назначение. К категории служебных относятся следующие методы:
public boolean equals(Object obj)
Сравнивает объект-получатель с объектом, на который указывает ссылка obj; возвращает true, если объекты равны между собой, и false в противном случае. Если вам нужно выяснить, указывают ли две ссылки на один и тот же объект, можете сравнить их с помощью операторов == и !=, а метод equals предназначен для сравнения значений. Реализация метода equals, принятая в Object по умолчанию, предполагает, что объект равен лишь самому себе.
public int hashCode()
Возвращает хеш-код для данного объекта. Каждому объекту может быть присвоен некоторый хеш-код, используемый при работе с хеш-таблицами. По умолчанию возвращается значение, которое является уникальным для каждого объекта. Оно используется при сохранении объектов в таблицах Hashtable, которые описаны в разделе “Класс Hashtable”.
protected Object clone()throws CloneNotSupportedException
Возвращаетдубликатобъекта.Дубликатом называется новый объект, являющийся копией объекта, для которого вызывался метод clone. Процесс дублирования объектов подробнее рассматривается ниже в этой главе, в разделе3.8.
public final Class getClass()
Возвращает объект типа Class, который соответствует классу данного объекта. Во время выполнения программы на Java можно получить информацию о классе в виде объекта Class, возвращаемого методом getClass.
protected void finalize() throws Throwable
Завершающие операции с объектом, осуществляемые во время сборки мусора. Этот метод был подробно описан в разделе “Метод finalize”.
Методы hashCode и equals должны переопределяться, если вы хотите ввести новую концепцию равенства объектов, отличающуюся от принятой в классе Object. По умолчанию считается, что два различных объекта не равны между собой, а их хеш-коды не должны совпадать.
Если ваш класс вводит концепцию равенства, при которой два различных объекта могут считаться равными, метод hashCode должен возвращать для них одинаковые значения хеш-кода. Это происходит оттого, что механизм Hashtable полагается в своей работе на возврат методом equals значения true при нахождении в хеш-таблице элемента с тем же значением. Например, класс Stringпереопределяет метод equals так, чтобы он возвращал значение true при совпадении содержимого двух строк. Кроме того, в этом классе переопределяется и метод hashCode— его новая версия возвращает хеш-код, вычисляемый на основании содержимого String, и две одинаковые строки имеют совпадающие значения хеш-кодов.
Упражнение 3.5
Переопределите методы equals и hashCode в классе Vehicle.
3.7. Абстрактные классы и методы
Абстрактные классыпредставляют собой исключительно полезную концепцию объектно-ориентированного программирования. С их помощью можно объявлять классы, реализованные лишь частично, поручив полную реализацию расширенным классам.
Абстракция оказывается полезной, когда некоторое поведение характерно для большинства или всех объектов данного класса, но некоторые аспекты имеют смысл лишь для ограниченного круга объектов, не составляющих суперкласса. В Java такие классы объявляются с ключевым словом abstract, и каждый метод, не реализованный в классе, также объявляется abstract. (Если все, что вам требуется,— это определить набор методов, которые будут где-то поддерживаться, но не предоставлять для них реализации, то вместо абстрактных классов, видимо, лучше воспользоваться интерфейсами, описанными в главе 4.)
Допустим, вы хотите создать инфраструктуру для написания кода, который будет во время выполнения программы измерять определенные показатели. Реализация такого класса может учитывать, как происходит измерение, но вы не знаете заранее, какой именно показатель будет измеряться. Большинство абстрактных классов следует именно этому принципу: для конкретной работы, выполняемой классом, необходимо, чтобы кто-то предоставил недостающую часть. В нашем примере таким недостающим звеном становится фрагмент программы, выполняющий измерения. Вот как может выглядеть соответствующий класс:
abstract class Benchmark {
abstract void benchmark();
public long repeat(int count) {
long start = System.currentTimeMillis();
for (int i = 0; i < count; i++)
benchmark();
return (System.currentTimeMillis() — start);
}
}
Класс объявлен с ключевым словом abstract, потому что так объявляется любой класс, содержащий абстрактные методы. Подобная избыточность позволяет во время чтения программы быстро понять, является ли данный класс абстрактным, и обойтись без просмотра всех методов и поиска среди них абстрактных.
Метод repeat предоставляет общую схему для проведения измерений. Он знает, как ему вызвать процедуру измерения count раз через равные интервалы времени. Если хронометраж должен быть более сложным (например, необходимо измерить время каждого запуска и вычислить статистику отклонения от среднего значения), метод можно усовершенствовать, что никак не отразится на реализации процедуры измерений в расширенном классе.
Абстрактный метод benchmark должен быть реализован в каждом подклассе, который не является абстрактным. Именно по этой причине в классе отсутствует реализация, есть лишь объявление. Приведем пример простейшего расширения класса Benchmark:
class MethodBenchmark extends Benchark {
void benchmark() {
}
public static void main(String[] args) {
int count = Integer.parseInt(args[0]);
long time = new MethodBenchmark().repeat(count);
System.out.println(count + “ methods in ” +
time + “ milliseconds”);
}
}
Данный класс использует benchmark для определения времени, затраченного на вызов метода. Теперь вы можете провести хронометраж, запустив приложение MethodBenchmark, сообщив ему количество повторений теста. Значение передается в программу в виде аргумента-строки, из которого оно извлекается методом parseInt класса Integer, как описано в разделе “Преобразование строк”.
Вы не можете создать объект абстрактного класса, поскольку для некоторых вызываемых методов может отсутствовать реализация.
Любой класс может переопределить методы своего суперкласса и объявить их абстрактными— конкретный метод в иерархии типов становится абстрактным. Это бывает полезно, например, когда принятая по умолчанию реализация класса не подходит на некоторых уровнях в его иерархии.
Упражнение 3.6
Напишите новый класс, который измеряет что-нибудь другое— например, время, затраченное на выполнение цикла от 0 до значения, переданного в виде параметра.
Упражнение 3.7
Измените класс Vehicle так, чтобы он содержал ссылку на объект EnergySource (источник энергии), ассоциируемый с Vehicle внутри конструктора. Класс EnergySource должен быть абстрактным, поскольку состояние заполнения для объекта GasTank (бензобак) должно отмечаться иначе, нежели для объекта Battery (аккумулятор). Включите в EnergySource абстрактный метод empty и реализуйте его в классах GasTank и Battery. Включите в Vehicle метод start, который бы проверял состояние источника энергии в начале поездки.