- •Аннотация
- •Лекция 1. Что такое Java? История создания.
- •1. Что такое Java?
- •2. История создания Java
- •2.1. Сложности внутри Sun Microsystems
- •2.2. Проект Green
- •2.3. Компания FirstPerson
- •2.4. World Wide Web
- •2.5. Возрождение Oak
- •2.6. Java выходит в свет
- •3. История развития Java
- •3.1. Браузеры
- •3.2. Сетевые компьютеры
- •3.3. Платформа Java
- •4. Заключение
- •5. Контрольные вопросы
- •Аннотация
- •1. Основы объектно-ориентированного программирования
- •1.1. Методология процедурно-ориентированного программирования
- •1.2. Методология объектно-ориентированного программирования
- •1.3. Объекты
- •1.3.1. Состояние.
- •1.3.2. Поведение
- •1.3.3. Уникальность
- •1.4. Классы
- •1.4.1. Инкапсуляция
- •1.4.2. Полиморфизм
- •1.5. Типы отношений между классами
- •1.5.1. Агрегация
- •1.5.2. Ассоциация
- •1.5.3. Наследование
- •1.5.4. Метаклассы
- •1.6. Достоинства ООП
- •1.7. Недостатки ООП
- •1.8. Заключение
- •1.9. Контрольные вопросы
- •Аннотация
- •Лекция 3. Лексика языка
- •1. Лексика языка
- •1.1. Кодировка
- •1.2. Анализ программы
- •1.2.1. Пробелы
- •1.2.2. Комментарии
- •1.2.3. Лексемы
- •1.3. Виды лексем
- •1.3.1. Идентификаторы
- •1.3.2. Ключевые слова
- •1.3.3. Литералы
- •1.3.3.1. Целочисленные литералы
- •1.3.3.2. Дробные литералы
- •1.3.3.3. Логические литералы
- •1.3.3.4. Символьные литералы
- •1.3.3.5. Строковые литералы
- •1.3.3.6. Null литерал
- •1.3.3.7. Разделители
- •1.3.3.8. Операторы
- •1.3.3.9. Заключение
- •1.4. Дополнение: Работа с операторами
- •1.4.1. Операторы присваивания и сравнения
- •1.4.2. Арифметические операции
- •1.4.3. Логические операторы
- •1.4.4. Битовые операции
- •1.5. Заключение
- •1.6. Контрольные вопросы
- •Аннотация
- •Лекция 4. Типы данных
- •1. Введение
- •2. Переменные
- •3. Примитивные и ссылочные типы данных
- •3.1. Примитивные типы
- •3.2. Целочисленные типы
- •4. Дробные типы
- •5. Булевский тип
- •6. Ссылочные типы
- •6.1. Объекты и правила работы с ними
- •6.2. Класс Object
- •6.3. Класс String
- •6.4. Класс Class
- •7. Заключение
- •8. Заключение
- •9. Контрольные вопросы
- •Аннотация
- •Лекция 5. Имена. Пакеты
- •1. Введение
- •2. Имена
- •2.1. Простые и составные имена. Элементы.
- •2.2. Имена и идентификаторы
- •2.3. Область видимости (введение)
- •3. Пакеты
- •3.1. Элементы пакета
- •3.2. Платформенная поддержка пакетов
- •3.3. Модуль компиляции
- •3.3.1. Объявление пакета
- •3.3.2. Импорт-выражения
- •3.3.3. Объявление верхнего уровня
- •3.4. Уникальность имен пакетов
- •4. Область видимости имен
- •4.1. "Затеняющее" объявление (Shadowing)
- •4.2. "Заслоняющее" объявление (Obscuring)
- •5. Соглашения по именованию
- •6. Заключение
- •7. Контрольные вопросы
- •Аннотация
- •Лекция 6. Объявление классов
- •1. Введение
- •2. Модификаторы доступа
- •2.1. Предназначение модификаторов доступа
- •2.2. Разграничение доступа в Java
- •3. Объявление классов
- •3.1. Заголовок класса
- •3.2. Тело класса
- •3.3. Объявление полей
- •3.4. Объявление методов
- •3.5. Объявление конструкторов
- •3.6. Инициализаторы
- •4. Дополнительные свойства классов
- •4.1. Метод main
- •4.2. Параметры методов
- •4.3. Перегруженные методы
- •5. Заключение
- •6. Контрольные вопросы
- •Аннотация
- •Лекция 7. Преобразование типов
- •1. Введение
- •2. Виды приведений
- •2.1. Тождественное преобразование
- •2.2. Преобразование примитивных типов (расширение и сужение)
- •2.3. Преобразование ссылочных типов (расширение и сужение)
- •2.4. Преобразование к строке
- •2.5. Запрещенные преобразования
- •3. Применение приведений
- •3.1. Присвоение значений
- •3.2. Вызов метода
- •3.3. Явное приведение
- •3.4. Оператор конкатенации строк
- •3.5. Числовое расширение
- •3.5.1. Унарное числовое расширение
- •3.5.2. Бинарное числовое расширение
- •4. Тип переменной и тип ее значения
- •5. Заключение
- •6. Контрольные вопросы
- •Аннотация
- •1. Введение
- •2. Статические элементы
- •3. Ключевые слова this и super
- •4. Ключевое слово abstract
- •5. Интерфейсы
- •5.1. Объявление интерфейсов
- •5.2. Реализация интерфейса
- •5.3. Применение интерфейсов
- •6. Полиморфизм
- •6.1. Поля
- •6.2. Методы
- •6.3. Полиморфизм и объекты
- •7. Заключение
- •8. Контрольные вопросы
- •Аннотация
- •Лекция 9. Массивы
- •1. Введение
- •2. Массивы, как тип данных в Java
- •2.1. Объявление массивов
- •2.2. Инициализация массивов
- •2.3. Многомерные массивы
- •2.4. Класс массива
- •3. Преобразование типов для массивов
- •3.1. Ошибка ArrayStoreException
- •3.2. Переменные типа массив, и их значения
- •4. Клонирование
- •4.1. Клонирование массивов
- •5. Заключение
- •6. Контрольные вопросы
- •Аннотация
- •Лекция 10. Операторы и структура кода
- •1. Управление ходом программы
- •2. Нормальное и прерванное выполнение операторов
- •3. Блоки и локальные переменные
- •4. Пустой оператор
- •5. Метки
- •6. Оператор if
- •7. Оператор switch
- •8. Управление циклами
- •8.1. Цикл while
- •8.2. Цикл do
- •8.3. Цикл for
- •9. Операторы break и continue
- •9.1. Оператор continue
- •9.2. Оператор break
- •10. Именованные блоки
- •11. Оператор return
- •12. Оператор synchronized
- •13.1. Причины возникновения ошибок
- •13.2. Обработка исключительных ситуаций
- •13.2.1. Конструкция try-catch
- •13.2.2. Конструкция try-catch-finally
- •13.3. Использование оператора throw
- •13.4. Обрабатываемые и необрабатываемые исключения
- •13.5. Создание пользовательских классов исключений
- •13.6. Переопределение методов и исключения
- •13.7. Особые случаи
- •14. Заключение
- •15. Контрольные вопросы
- •Аннотация
- •Лекция 11. Пакет java.awt
- •1. Введение
- •2. Апплеты
- •2.1. Тег HTML <Applet>
- •2.2. Передача параметров
- •2.3. Контекст апплета
- •2.4. Отладочная печать
- •2.5. Порядок инициализации апплета
- •2.6. Перерисовка
- •2.7. Задание размеров графических изображений
- •2.8. Простые методы класса Graphics
- •2.9. Цвет
- •2.9.1. Методы класса Color
- •2.10. Шрифты
- •2.10.1. Использование шрифтов
- •2.10.2. Позиционирование и шрифты: FontMetrics
- •2.10.3. Использование FontMetrics
- •2.10.4. Центрирование текста
- •3. Базовые классы
- •4. Основные компоненты
- •5. Менеджеры компоновки
- •6. Окна
- •7. Меню
- •8. Обработка событий
- •8.1. Рисование "каракулей" в Java
- •8.2. Рисование "каракулей" с использованием встроенных классов
- •9. Заключение
- •10. Контрольные вопросы
- •Аннотация
- •Лекция 12. Потоки выполнения. Синхронизация
- •1. Введение
- •2. Многопоточная архитектура
- •3. Базовые классы для работы с потоками
- •3.1. Класс Thread
- •3.2. Интерфейс Runnable
- •3.3. Работа с приоритетами
- •3.4. Демон-потоки
- •4. Синхронизация
- •4.1. Хранение переменных в памяти
- •4.2. Модификатор volatile
- •4.3. Блокировки
- •5. Методы wait(), notify(), notifyAll() класса Object
- •6. Контрольные вопросы
- •Аннотация
- •Лекция 13. Пакет java.lang.
- •1. Введение
- •2. Object
- •3. Class
- •4. Wrapper Classes
- •4.1. Integer
- •4.2. Character
- •4.3. Boolean
- •4.4. Void
- •5. Math
- •6. Строки
- •6.1. String
- •6.2. StringBuffer
- •7. Системные классы
- •7.1. ClassLoader
- •7.2. SecurityManager - менеджер безопасности
- •7.3. System
- •7.4. Runtime
- •7.5. Process
- •8. Потоки исполнения
- •8.1. Runnable
- •8.2. Thread
- •8.3. ThreadGroup
- •9. Исключения
- •10. Заключение
- •11. Контрольные вопросы
- •Аннотация
- •Лекция 14. Пакет java.util
- •1. Введение
- •2. Работа с датами и временем
- •2.1. Класс Date
- •2.2. Классы Calendar и GregorianCalendar
- •2.3. Класс TimeZone
- •2.4. Класс SimpleTimeZone
- •3. Интерфейс Observer и класс Observable
- •4. Коллекции
- •4.1. Интерфейсы
- •4.1.1. Интерфейс Collection
- •4.1.2. Интерфейс Set
- •4.1.3. Интерфейс List
- •4.1.4. Интерфейс Map
- •4.1.5. Интерфейс SortedSet
- •4.1.6. Интерфейс SortedMap
- •4.1.7. Интерфейс Iterator
- •4.2. Aбстрактные классы используемые при работе с коллекциями.
- •4.3. Конкретные классы коллекций
- •4.4. Класс Collections
- •5. Класс Properties
- •6. Интерфейс Comparator
- •7. Класс Arrays
- •8. Класс StringTokenizer
- •9. Класс BitSet
- •10. Класс Random
- •11. Локализация
- •11.1. Класс Locale
- •11.2. Класс ResourceBundle
- •12. Заключение
- •13. Контрольные вопросы
- •Аннотация
- •Лекция 15. Пакет java.io
- •1. Система ввода/вывода. Потоки данных (stream)
- •1.1. Классы InputStream и OutputStream
- •1.2. Классы-реализации потоков данных
- •1.2.1. Классы ByteArrayInputStream и ByteArrayOutputStream
- •1.2.2. Классы FileInputStream и FileOutputStream
- •1.2.3. PipedInputStream и PipedOutputStream
- •1.2.4. StringBufferInputStream
- •1.2.5. SequenceInputStream
- •1.3. Классы FilterInputStreeam и FilterOutputStream. Их наследники.
- •1.3.1. BufferedInputStream и BufferedOutputStream
- •1.3.2. LineNumberInputStream
- •1.3.3. PushBackInputStream
- •1.3.4. PrintStream
- •1.3.5. DataInputStream и DataOutputStream
- •2. Serialization
- •2.1. Версии классов
- •3. Классы Reader и Writer. Их наследники.
- •4. Класс StreamTokenizer
- •5. Работа с файловой системой.
- •5.1. Класс File
- •5.2. Класс RandomAccessFile
- •6. Заключение
- •7. Контрольные вопросы
- •Аннотация
- •Лекция 16. Введение в сетевые протоколы
- •1. Основы модели OSI
- •2. Physical layer (layer 1)
- •3. Data layer (layer 2)
- •3.1. LLC sublayer.
- •3.2. MAC sublayer.
- •4. Network layer (layer 3)
- •4.1. Class A
- •4.2. Class B
- •4.3. Class CClass DClass E
- •5. Transport layer (layer 4)
- •6. Session layer (layer 5)
- •7. Presentation layer (layer 6)
- •8. Application layer (layer 7)
- •9. Утилиты для работы с сетью
- •9.1. IPCONFIG (IFCONFIG)
- •9.3. Ping
- •9.4. Traceroute
- •9.5. Route
- •9.6. Netstat
- •9.7. Задания для практического занятия
- •10. Пакет java.net
- •11. Заключение
- •12. Контрольные вопросы
Стр. 16 из 33 |
Объявление классов |
Видно, что хотя тело метода содержит return-выражение, однако не при любом развитии событий возвращаемое значение будет сгенерировано. А вот такой пример является правильным:
public int get() { if (condition) {
return 5; } else {
return 3;
}
}
Конечно, значение, указанное после слова return, должно быть совместимое по типу с объявленным возвращаемым значением (это понятие подробно рассматривается в главе "Преобразование типов").
В методе без возвращаемого значения (указано void) также можно использовать выражение return без каких либо аргументов. Его можно указать в любом месте метода, в этой точке выполнение метода будет завершено:
public void calculate(int x, int y) { if (x<=0 || y<=0) {
return; // некорректные входные значения, выход из метода
}
... // основные вычисления
}
Выражений return (с параметром или без для методов с/без возвращаемого значения) в теле одного метода может быть сколько угодно. Однако, следует помнить, что множество точек выхода в одном методе может серьезно усложнить понимание логики его работы.
3.5. Объявление конструкторов
Формат объявления конструкторов похож на упрощенное объявление методов. Также выделяют заголовок и тело конструктора. Заголовок состоит, во-первых, из модификаторов доступа (никакие другие модификаторы не допустимы). Затем указывается имя класса, которое можно расценивать двояко. Можно считать, что имя конструктора совпадает с именем класса. А можно рассматривать конструктор как безымянный, а имя класса - как тип возвращаемого значения, ведь конструктор может породить только объект класса, в котором он объявлен. Это исключительно дело вкуса, так как на формате объявления никак не сказывается:
public class Human { private int age;
protected Human(int a) { age=a;
}
Программирование на Java
Rendered by www.RenderX.com
Объявление конструкторов |
Стр. 17 из 33 |
public Human(String name, Human mother, Human father) { age=0;
}
}
Как видно из примеров, далее следует перечисление входных аргументов по тем же правилам, что и для методов. Также завершает заголовок конструктора throws-выражение. Оно имеет особую важность для конструкторов, поскольку создать ошибку - это единственный способ для конструктора не создавать объект. Если конструктор выполнился без ошибок, то объект гарантированно создается.
Тело конструктора пустым быть не может и поэтому всегда описывается в фигурных скобках (для простейших реализаций скобки могут быть пустыми).
В отсутствие имени (или, что то же самое, из-за того, что у всех конструкторов одинаковое имя, совпадающее с именем класса) сигнатура конструктора определяется только набором входных параметров по тем же правилам, что и для методов. Аналогично, в одном классе допускается любое количество конструкторов, если у них различные сигнатуры.
Тело конструктора может содержать любое количество return-выражений без аргументов. Если процесс исполнения дойдет до такого выражения, то на этом месте выполнение конструктора будет завершено.
Однако логика работы конструкторов имеет и некоторые важные особенности. Поскольку при их вызове осуществляется создание и инициал»изация объекта, то становится понятно, что такой процесс не может происходить без обращения к конструкторам всех родительских классов. Поэтому вводится обязательное правило - первой строкой в конструкторе должно быть обращение к родительскому классу, которое записывается с помощью ключевого слова super.
public class Parent { private int x, y;
public Parent() { x=y=0;
}
public Parent(int newx, int newy) { x=newx;
y=newy;
}
}
public class Child extends Parent { public Child() {
super();
}
public Child(int newx, int newy) { super(newx, newy);
Программирование на Java
Rendered by www.RenderX.com
Стр. 18 из 33 |
Объявление классов |
}
}
Как видно, обращение к родительскому конструктору записывается с помощью super, за которым идет перечисление аргументов. Этот набор определяет, какой из родительских конструкторов будет использован. В приведенном примере в каждом классе есть по 2 конструктора, и каждый конструктор в наследнике обращается к аналогичному в родителе (это довольно распространенный, но, конечно, не обязательный способ).
Проследим мысленно весь алгоритм создания объекта. Он начинается при исполнении выражения с ключевым словом new, за которым следует имя класса, от которого будет порождаться объект, и набор аргументов для его конструктора. По этому набору определяется, какой именно конструктор будет использован, и происходит его вызов. Первая строка его тела содержит вызов родительского конструктора. В свою очередь, первая строка тела конструктора родителя будет содержать вызов далее к его родителю
итак далее. Восхождение по дереву наследования заканчивается, очевидно, на классе Object, у которого есть единственный конструктор без параметров. Его тело пустое (в смысле, записывается парой пустых фигурных скобок), однако можно считать, что именно в этот момент JVM порождает объект, и далее начинается процесс его инициализации. Выполнение начинает обратный путь вниз по дереву наследования. У самого верхнего родителя, прямого наследника от Object, происходит продолжение исполнения конструктора со второй строки. Когда он будет полностью выполнен, необходимо перейти к следующему родителю на один уровень наследования вниз и завершить выполнение его конструктора
итак далее. Наконец, можно будет вернуться к конструктору исходного класса, который был вызван с помощью new, и также продолжить его выполнение со второй строки. По его завершению объект считается полностью созданным, исполнение выражения new будет закончено, а в качестве результата будет возвращена ссылка на порожденный объект.
Проиллюстрируем этот алгоритм следующим примером:
public class GraphicElement {
private int x, y; // положение на экране
public GraphicElement(int nx, int ny) {
super(); // обращение к конструктору родителя Object System.out.println("GraphicElement");
x=nx;
y=nx;
}
}
public class Square extends GraphicElement { private int side;
public Square(int x, int y, int nside) { super(x, y); System.out.println("Square"); side=nside;
}
}
Программирование на Java
Rendered by www.RenderX.com
Объявление конструкторов |
Стр. 19 из 33 |
public class SmallColorSquare extends Square { private Color color;
public SmallColorSquare(int x, int y, Color c) { super(x, y, 5); System.out.println("SmallColorSquare"); color=c;
}
}
После выполнения выражения создания объекта на экране появится следующее:
GraphicElement
Square
SmallColorSquare
Выражение super может стоять только на первой строке конструктора. Часто можно увидеть конструкторы вообще без такого выражения. В этом случае компилятор первой строкой по умолчанию добавляет вызов родительского конструктора без параметров (super()). Если у родительского класса нет такого конструктора, выражение super обязательно должно быть записано явно (и именно на первой строке), поскольку необходима передача входных параметров.
Напомним, что, во-первых, конструкторы не имеют имени и их нельзя вызвать явно, только через выражение создания объекта. Кроме того, конструкторы не передаются по наследству. То есть, если в родительском классе объявлено пять разных полезных конструкторов, и требуется, чтобы класс-наследник имел аналогичный набор, необходимо их все заново описать.
Класс обязательно должен иметь конструктор, иначе невозможно порождать объекты ни от него, ни от его наследников. Поэтому если в классе не объявлен ни один конструктор, компилятор добавляет один по умолчанию. Это public-конструктор без параметров и с телом, описанным парой пустых фигурных скобок. Из этого следует, что такое возможно только для классов, у родителей которых объявлен конструктор без параметров, иначе возникнет ошибка компиляции. Обратите внимание, что если затем в такой класс добавляется конструктор (не важно, с параметрами или без), то конструктор по умолчанию больше не вставляется:
/* * Этот класс имеет один конструктор. */
public class One {
//Будет создан конструктор по умолчанию
//Родительский класс Object имеет
//конструктор без параметров.
}
/*
Программирование на Java
Rendered by www.RenderX.com
Стр. 20 из 33 |
Объявление классов |
* Этот класс имеет один конструктор. */
public class Two {
//Единственный конструктор класса Second.
//Выражение new Second() ошибочно! public Second(int x) {
}
}
/* * Этот класс имеет два конструктора. */
public class Three extends Two { public Three() {
super(1); // выражение super требуется
}
public Three(int x) {
super(x); // выражение super требуется
}
}
В случае если класс имеет более одного конструктора, допускается в первой строке некоторых из них указывать не super, а this - выражение, вызывающее другой конструктор этого же класса.
Рассмотрим следующий пример:
public class Vector { private int vx, vy; protected double length;
public Vector(int x, int y) { super();
vx=x;
vy=y;
length=Math.sqrt(vx*vx+vy*vy);
}
public Vector(int x1, int y1, int x2, int y2) { super();
vx=x2-x1; vy=y2-y1;
length=Math.sqrt(vx*vx+vy*vy);
}
}
Видно, что оба конструктора совершают практически идентичные действия, поэтому можно применить более компактный вид записи:
Программирование на Java
Rendered by www.RenderX.com
Объявление конструкторов |
Стр. 21 из 33 |
public class Vector { private int vx, vy; protected double length;
public Vector(int x, int y) { super();
vx=x;
vy=y;
length=Math.sqrt(vx*vx+vy*vy);
}
public Vector(int x1, int y1, int x2, int y2) { this(x2-x1, y2-y1);
}
}
Большим достоинством такого метода записи является то, что удалось избежать дублирования идентичного кода. Например, если процесс инициализации объектов этого класса удлинится на один шаг (скажем, добавится проверка длины на ноль), то такое изменение надо будет внести только в одно место - в первый конструктор. Такой подход помогает избегать случайных ошибок, так как исчезает необходимость тиражировать изменения в нескольких местах.
Разумеется, такое обращение к конструкторам своего класса не должно приводить к зацикливаниям, иначе будет выдана ошибка компиляции. Цепочка this должна в итоге приводить к super, который должен присутствовать (явно или неявно) хотя бы в одном из конструкторов. После того, как отработают конструкторы всех родительских классов, будет продолжено выполнение каждого конструктора, вовлеченного в процесс создания объекта.
После выполнения выражения new Test(0) на консоли появится:
Test()
Test(int x)
В заключение рассмотрим применение модификаторов доступа для конструкторов. Может вызвать удивление возможность объявлять конструкторы как private. Ведь они нужны для порождения объектов, а к таким конструкторам ни у кого не будет доступа. Однако в ряде случаев модификатор private может быть полезен. Например:
•private-конструктор может содержать инициализирующие действия, а остальные конструкторы будут использовать его с помощью this, причем прямое обращение к этому конструктору по каким-то причинам нежелательно;
•запрет на создание объектов этого класса, например, невозможно создать экземпляр класса Math;
•реализация специального шаблона проектирования из ООП Singleton, для работы которого требуется контролировать создание объектов, что невозможно в случае наличия не-private конструкторов.
Программирование на Java
Rendered by www.RenderX.com