- •Аннотация
- •Лекция 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 из 22 |
Тип переменной и тип ее значения |
Операторы сдвига имеют два аргумента, но они расширяются независимо друг от друга, поэтому это преобразование является унарным. Таким образом, результат выражения 5<<3L имеет тип int. Вообще, результат операторов сдвига всегда имеет тип int или long.
Примеры работы всех этих операторов с учетом расширения подробно рассматривались в предыдущих главах.
3.5.2. Бинарное числовое расширение
Это преобразование расширяет все примитивные числовые типы кроме double до типов int, long, float, double по правилам расширения примитивных типов. Бинарное числовое расширение происходит при числовых операторах, имеющих два аргумента, по следующим правилам:
•если любой из аргументов имеет тип double, то и второй приводится к double;
•иначе, если любой из аргументов имеет тип float, то и второй приводится к float;
•иначе, если любой из аргументов имеет тип long, то и второй приводится к long;
•иначе оба аргумента приводятся к int.
Бинарное числовое расширение может происходить при следующих операциях:
•арифметические операции +, -, *, /, %;
•операции сравнения <, <=, >, >=, ==, !=;
•битовые операции &, |, ^;
•в некоторых случаях для операции с условием ? :.
Примеры работы всех этих операторов с учетом расширения подробно рассматривались в предыдущих главах.
4. Тип переменной и тип ее значения
Теперь, когда были подробно рассмотрены все примеры преобразований, нужно вернутся к вопросу переменной и ее значений.
Как уже говорилось, переменная определяется тремя базовыми характеристиками: имя, тип, значение. Имя дается произвольным образом и никак не сказывается на свойствах переменной. А вот значение всегда имеет некоторый тип, не обязательно совпадающий с типом самой переменной. Поэтому необходимо рассмотреть все возможные типы переменных и выяснить, значения каких типов они могут в себе хранить.
Начнем с переменных примитивных типов. Поскольку эти переменные действительно хранят само значение, то их тип всегда точно совпадает с типом значения.
Проиллюстрируем это правило на примере:
byte b=3; char c='A'+3; long m=b+c; double d=m-3F;
Программирование на Java
Rendered by www.RenderX.com
Стр. 17 из 22
Здесь переменная b будет хранить значение типа byte после сужения целочисленного литерала типа int. Переменная c будет хранить тип char после того, как компилятор осуществит сужающее преобразование результата суммирования, который будет иметь тип int. Для переменной l выполнится расширения результата суммирования типа от int к типу long. Наконец, переменная d будет хранить значение типа double, получившееся в результате расширения результата разности, который имеет тип float.
Переходим к ссылочным типам. Во-первых, значение любой переменной такого типа - ссылка, которая может указывать только на объекты, порожденные от тех или иных классов, и далее обсуждаются только свойства этих классов. (Также объекты могут порождаться от массивов, эта тема рассматривается в отдельной главе).
Кроме этого, ссылочная переменная любого типа может иметь значение null. Большинство действий над такой переменной, например, обращение к полям или методам, приведет к ошибке.
Итак, какова связь между типом ссылочной переменной и ее значения? Здесь главное ограничение - проверка компилятора, который следит, чтобы все действия, выполняющиеся над объектом, были корректны. Компилятор не может предугадать, на объект какого класса будет реально ссылаться та или иная переменная. Все, чем он располагает - тип самой переменной. Именно его и использует компилятор для проверок. А значит, все допустимые значения переменной должны гарантировано обладать свойствами, определенными в классе-типе этой переменной. Такую гарантию дает только наследование. Отсюда получаем правило: ссылочная переменная типа A может указывать на объекты, порожденные от самого типа A или его наследников.
Point p = new Point();
В этом примере переменная и ее значение одинакового типа, поэтому над объектом можно совершать все возможные для данного класса действия.
Parent p = new Child();
Такое присвоение корректно, так как класс Child порожден от Parent. Однако теперь допустимые действия над переменной p, а значит, над объектом, только что созданным на основе класса Child, ограничены только теми, которые были унаследованы от класса Parent. Например, если в классе Child определен некий новый метод newChildMethod(), то попытка его вызвать p.newChildMethod() будет порождать ошибку компиляции. Необходимо подчеркнуть, что не происходит никаких изменений с самим объектом, ограничение порождается используемым способом доступа к этому объекту - переменной типа Parent.
Чтобы показать, что объект не потерял никаких своих свойств, произведем следующее обращение:
((Child)p).newChildMethod();
Здесь в начале проводится явное сужение к типу Child. Во время исполнения программы JVM проверит, что тип объекта, на который ссылается переменная p совместим с типом Child. В нашем случае это именно так. В результате получается ссылка типа Child, поэтому становится допустимым вызов метода newChildMethod(), который вызывается у объекта, созданного в предыдущей строке.
Программирование на Java
Rendered by www.RenderX.com
Стр. 18 из 22 |
Заключение |
Обратим внимание на важный частный случай - переменная типа Object может ссылаться на объекты любого типа.
В дальнейшем, с изучением новых типов (абстрактных классов, интерфейсов, массивов) этот список будет продолжаться, а пока приведем краткое обобщение того, что было рассмотрено в этом разделе.
Тип переменной |
|
Допустимые типы ее значения |
Примитивный |
В точности совпадает с типом переменной |
|
Ссылочный |
• |
null |
|
• совпадающий с типом переменной |
|
|
• классы-наследники от типа переменной |
|
Object |
• |
null |
|
• |
любой ссылочный |
5. Заключение
В этой главе были рассмотрены правила работы с типами данных в строго типизированном языке Java. Поскольку компилятор строго отслеживает тип каждой переменной и каждого выражения, в случае изменения этого типа необходимо четко понимать, какие действия допустимы, а какие нет, с точки зрения компилятора и виртуальной машины.
Были рассмотрены все виды приведения типов в Java, то есть переход от одного типа к другому. Они разбиваются на 7 групп, начиная с тождественного и заканчивая запрещенными. Основные 4 вида определяются сужающими или расширяющими переходами между простыми или ссылочными типами. Важно помнить, что при явном сужении числовых типов, старшие биты просто отбрасываются, что порой приводит к неожиданному результату. Что касается преобразования ссылочных значений, то здесь действует правило – преобразование никогда не порождает новых и не изменяет существующих объектов. Меняется лишь способ работы с ними.
Особенными в Java является преобразование к строке.
Затем были рассмотрены все ситуации в программе, где могут происходить преобразования типов. Во-первых, это присвоение значений, когда зачастую преобразование происходит не заметно для программиста. Вызов метода во многом похож на инициализацию. Явное приведение позволяет осуществить желаемый переход в случае, когда компилятор не позволяет сделать это неявно. Преобразование при выполнении числовых операций оказывает существенное влияние на результат.
В заключение была рассмотрена связь между типом переменной и типом ее значения.
6. Контрольные вопросы
7-1. Корректен ли следующий пример кода, и если да, то сколько преобразований и каких видов будет произведено при его исполнении?
byte b=1; long m=-b; Object o=”=”;
Программирование на Java
Rendered by www.RenderX.com
Стр. 19 из 22
print(“m”+o+m);
a.) Пример корректен. Преобразования:
•первая строка: преобразование при присвоении, сужение от int к byte
•вторая: числовое расширение при вычислении оператора унарный минус от byte к int, расширение при присвоении значения от int к long
•третья: расширение при присвоении String к Object
•четвертая: приведения к строке: от Object к String и от long к String (через Long).
7-2. Произойдет ли потеря точности при следующем преобразовании?
float f = -16777217;
a.) Да. Число 16777217 записывается как 1000000000000000000000001 в
двоичной системе, всего 25 бит. А тип float отводит 24 бита для хранения мантиссы (значащих цифр), причем один из них знаковый. После отбрасывания не уместившихся битов получаем
1000000000000000000000000, или –16777216 в десятичной системе. Таким образом, теряется точность в последнем разряде. (Для получения правильного ответа достаточно запустить подобный пример и увидеть результат.)
7-3. Корректен ли следующий пример? Если нет, то в каких строках какие ошибки будут сгенерированы?
byte b=100-100; byte b=100+100; byte b=100*100;
a.) Результат вычитания в первой строке равен 0, что укладывается в тип byte, ошибки не будет. Результат вычислений в строках 2 и 3 выходит за рамки byte (максимально допустимое значение 127), поэтому неявное сужение не допустимо.
7-4. Для каких значений числовой переменной x будет верно следующее выражение?
x==-x
a.) Для целочисленных типов:
•0
•самое наименьшее значение для типов int и long. Например, для типа int это –2147483648
Для дробных типов:
•значения 0.0 и –0.0
Программирование на Java
Rendered by www.RenderX.com
Стр. 20 из 22 |
Контрольные вопросы |
7-5. Верны ли следующие выражения для переменной d дробного типа?
(short)d==(short)(int)d
(int)d==(int)(long)d
a.) Первое выражение верно, так как при приведении к short, дробное значение всегда сначала приводится к int.
Второе выражение не верно, в чем можно легко убедится, вычислив его для любого d, большего, чем максимально допустимое значение типа int. Левая часть будет равна 231-1, в то время как правая будет вычислена путем отбрасывания битов, старше 32:
double d=3e9; System.out.println((int)d); System.out.println((int)(long)d);
Результатом будет:
2147483647 -1294967296
7-6. Корректны ли следующие преобразования?
Object o = (String)null;
String s = o;
a.) Нет. Хотя значение null можно привести к любому ссылочному типу, во 2 строке происходит сужение типа ссылки (Object) до класса String. Такое действие должно происходить явно:
String s = (String)o;
7-7. Пусть классы Wolf и Rabbit являются наследниками класса Animal. Корректен ли следующий пример?
Wolf w = new Wolf();
Animal a = (Animal)w;
Rabbit r = (Rabbit)a;
a.) Хотя этот пример будет корректно скомпилирован, при выполнении он всегда будет порождать ошибку. Не смотря на приведение, переменная «а» ссылается на объект типа Wolf, созданный в первой строке.
В третьей строке при приведении ссылки на объект класса Wolf к типу Rabbit будет возникать ошибка преобразования типов, поскольку эти классы не находятся на одной ветви дерева наследования.
7-8. Какие значения не могут участвовать в преобразовании к строке?
Программирование на Java
Rendered by www.RenderX.com
Стр. 21 из 22
a.) Все могут.
7-9. Какие преобразования будут производиться при работе следующего метода?
public int add(byte a, byte b) { short x=(short)a;
char y=(char)b; return x+y;
}
a.) Преобразования:
•первая строка: явное приведение от byte к short
•вторая: явное приведение от byte к char
•третья: числовое расширение при вычислении бинарного оператора сложения: от short и char к int
7-10. Какое значение появится на консоли после выполнения следующего кода?
char c=65; print(c); print(+c); print(“=”+c);
a.) Ответ:
A 65 =A
В первом случае выводится значение типа char, поэтому отображается символ. Во втором случае выводится значение унарного оператора плюс, то есть число типа int. В третьем случае при сложении со строкой происходит преобразование от типа char к String, то есть запишется символ.
7-11. Значение какого типа будет хранить переменная после инициализации?
byte b=1+2;
a.) Примитивные переменные всегда хранят значения точного того же типа, что и они сами, то есть, в данном примере – byte. Это значение будет получено после неявного сужения при присвоении от типа int.
7-12. Значения какого типа будут хранить переменные после инициализации?
Object o = “123”;
Child c = new Child();
Parent p=(Parent)new Child();
Программирование на Java
Rendered by www.RenderX.com
Стр. 22 из 22 |
Контрольные вопросы |
Child x=null;
a.) В порядке следования:
•String
•Child
•Child
•null
Программирование на Java
Rendered by www.RenderX.com