![](/user_photo/2706_HbeT2.jpg)
- •Кен Арнольд Джеймс Гослинг Дэвид Холмс Язык программирования 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
- •Приложение в Полезные таблицы
2.5. Конструкторы
Каждый вновь созданный объект обладает некоторым исходным состоянием. Значения полей могут инициализироваться при их объявлении— иногда этого бывает достаточно. /Инициализация данных подробно рассматривается в разделе "Инициализация", однако в сущности за этим термином скрывается обычное присвоение начального значения. Если в программе полю не присваивается никакого значения, оно получит значение ноль, \u0000, false или null, в зависимости от типа./ Однако довольно часто для определения исходного состояния простой инициализации данных оказывается недостаточно; например, могут понадобиться какие-либо исходные данные, или же выполняемые операции не могут быть представлены в виде простого присваивания.
Для тех случаев, когда простой инициализации недостаточно, используются конструкторы. Имя конструктора совпадает с именем класса, который он инициализирует. Конструкторы, подобно методам, могут получать один или несколько параметров, однако они не являются методами и не могут возвращать никакого значения. Параметры конструктора (если они есть) указываются в скобках за именем типа при создании объекта оператором new. Конструктор вызывается после того, как переменным в экземпляре вновь создаваемого объекта будут присвоены начальные значения по умолчанию и будет выполнена непосредственная инициализация.
В усовершенствованной версии класса Body исходное состояние объекта частично устанавливается посредством инициализации, а частично— в конструкторе:
class Body {
public long idNum;
public String name = “”;
public Body orbits = null;
private static long nextID = 0;
Body() {
idNum = nextID++;
}
}
Конструктор класса Body вызывается без аргументов, однако он выполняет важную функцию, а именно устанавливает во вновь создаваемом объекте правильное значение поля idNum. Простейшая ошибка, возможная при работе со старой версией класса,— скажем, вы забыли присвоить значение полю idNum или не наращивали nextID после его использования— приводила к тому, что в программе возникали разные объекты класса Body с одинаковыми значениями поля idNum. В результате возникали проблемы в той части кода, которая была основана на положении контракта, гласящем: “Все значения idNum должны быть разными”.
Возлагая ответственность за генерацию значений idNum на сам класс Body, мы тем самым предотвращаем ошибки подобного рода. Конструктор Body становится единственным местом в программе, где idNum присваивается значение. Следующим шагом является объявление поля nextID с ключевым словом private, чтобы доступ к нему осуществлялся только из класса. Тем самым мы устраняем еще один возможный источник ошибок для программистов, работающих с классом Body.
Кроме того, такое решение позволит нам свободно изменять способ присвоения значений полю idNums в объектах Body. Например, будущая реализация нашего класса может просматривать базу данных известных астрономических объектов и присваивать новое значение idNum лишь в том случае, если ранее данному небесному телу не был присвоен другой идентификатор. Такое изменение никак не скажется на существующем коде программы, поскольку он никак не участвует в присвоении значения idNum.
При инициализации полям name и orbits присваиваются некоторые разумные начальные значения. Следовательно, после приведенного ниже вызова конструктора все поля нового объекта Body будут инициализированы. После этого вы можете изменить состояние объекта, присвоив его полям нужные значения:
Body sun = new Body(); // значение idNum равно 0
sun.name = “Sol”;
Body earth = new Body(); // значение idNum равно 1
earth.name = “Earth”;
earth.orbits = sun;
Конструктор Body вызывается при создании нового объекта оператором new, но после того, как полям name и orbits будут присвоены начальные значения. Инициализация поля orbits значением null означает, что sun.orbits в нашей программе не присваивается никакого значения.
Если создание объекта для небесного тела с двумя параметрами— названием и центром обращения— будет происходить довольно часто, то можно предусмотреть отдельный конструктор, в который оба этих значения передаются в качестве параметров:
Body(String bodyName, Body orbitsAround) {
this();
name = bodyName;
orbits = orbitsAround;
}
Как видите, из одного конструктора можно вызывать другой конструктор этого же класса— для этого первым выполняемым оператором должен быть вызов this(). Это называется “явным вызовом конструктора”. Если для вызова конструктора необходимы параметры, они могут передаваться. В нашем случае для присвоения значения полю idNum используется конструктор, вызываемый без аргументов. Теперь создание объектов происходит значительно проще:
Body sun = new Body(“Sol”, null);
Body earth = new Body(“Earth”, sun);
При желании можно задать отдельный конструктор с одним аргументом для тех случаев, когда для создаваемого объекта Body не существует центра вращения. Вызов такого конструктора равносилен применению конструктора с двумя аргументами, при котором второй из них равен null.
Для некоторых классов необходимо, чтобы создатель объекта предоставлял некоторые данные. Например, приложение может требовать, чтобы для всех объектов Body было указано их название. Чтобы убедиться, что всем создаваемым объектам Body передается название, необходимо включить соответствующий параметр во все конструкторы класса Body.
Приведем несколько общепринятых соображений в пользу создания специализированных конструкторов:
Некоторые классы не обладают разумным начальным состоянием, если не передать им параметры.
При конструировании объектов некоторых видов передача исходного состояния оказывается самым удобным и разумным выходом (примером может служить конструктор Body с двумя аргументами).
Конструирование объектов потенциально сопряжено с большими накладными расходами, так что желательно при создании объекта сразу устанавливать правильное исходное состояние. Например, если каждый объект класса содержит таблицу, то конструктор, получающий исходный размер таблицы в качестве параметра, позволит с самого начала создать объект с таблицей нужного размера.
Конструктор, атрибут доступа которого отличается от public, ограничивает возможности создания объектов данного класса. Например, вы можете запретить программистам, работающим с вашим пакетом, расширять тот или иной класс, если сделаете все конструкторы доступными лишь из пакета. Кроме того, можно пометить ключевым словом protected те конструкторы, которые предназначены для использования исключительно в подклассах.
Конструкторы, не получающие при вызове никаких аргументов, встречаются настолько часто, что для них даже появился специальный термин: “безаргументные” (no-arg) конструкторы.
Если вы не предоставите для класса никаких конструкторов, язык создает безаргументный конструктор по умолчанию, который не делает ничего. Этот конструктор создается автоматически лишь в тех случаях, когда нет никаких других конструкторов,— существуют классы, для которых безаргументный конструктор будет работать неверно (например, класс Attr, с которым мы познакомимся в следующей главе).
Если безаргументный конструктор должен существовать наряду с одним или несколькими конструкторами, использующими аргументы, можно явно определить его. Автоматически создаваемый безаргументный конструктор класса, не имеющего суперкласса, эквивалентен следующему (как мы увидим на примере расширенного класса в главе 3):
class SimpleClass {
/** Эквивалент конструктора по умолчанию */
public SimpleClass() {
}
}
Конструктор по умолчанию имеет атрибут public, если такой же атрибут имеет класс, и не имеет его в противном случае.
Упражнение 2.6
Включите в класс Vehicleдва конструктора. Первый из них— безаргументный, а другойдолжен получать в качестве аргумента имя владельца машины. Модифицируйте метод main так, чтобы он выдавал те же результаты, что и раньше.
Упражнение 2.7
Какие конструкторы вы бы сочли нужным добавить в класс LinkedList?