Главная      Учебники - Разные     Лекции (разные) - часть 18

 

поиск по сайту           правообладателям

 

Общие представления о языке Java 5

 

             

Общие представления о языке Java 5

Содержание

Введение.......................................................................................................................................................................................... 6

Глава 1. Общие представления о языке Java........................................................................................................................ 7

1.1. Java и другие языки программирования. Системное и прикладное программирование............................ 7

1.2. Виртуальная Java-машина, байт-код, JIT-компиляция. Категории программ, написанных на языке Java 11

1.3.Алфавит языка Java. Десятичные и шестнадцатеричные цифры и целые числа. Зарезервированные слова 16

Алфавит языка Java......................................................................................................................................................... 16

Десятичные и шестнадцатеричные цифры и целые числа................................................................................... 16

Зарезервированные слова языка Java........................................................................................................................ 18

1.4. Управляющие последовательности. Символы Unicode. Специальные символы........................................ 18

Управляющие последовательности............................................................................................................................ 18

Простые специальные символы................................................................................................................................... 19

Составные специальные символы............................................................................................................................... 20

1.5.Идентификаторы. Переменные и типы. Примитивные и ссылочные типы..................................................... 21

Краткие итоги по главе 1..................................................................................................................................................... 24

Задания..................................................................................................................................................................................... 25

Глава 2. Объектно-ориентированное проектирование и платформа NetBeans....................................................... 26

2.1.Процедурное и объектно-ориентированное программирование. Инкапсуляция........................................ 26

2.2. Работа со ссылочными переменными. Сборка мусора...................................................................................... 29

2.3. Проекты NetBeans. Пакеты. Уровни видимости классов. Импорт классов................................................... 33

2.4. Базовые пакеты и классы Java................................................................................................................................... 35

2.5. Создание в NetBeans простейшего приложения Java......................................................................................... 38

2.6. Компиляция файлов проекта и запуск приложения............................................................................................. 42

2.7. Структура проекта NetBeans..................................................................................................................................... 43

2.8. Создание в NetBeans приложения Java с графическим интерфейсом............................................................ 46

2.9. Редактор экранных форм............................................................................................................................................. 49

2.10. Внешний вид приложения......................................................................................................................................... 53

2.11. Ведение проектов........................................................................................................................................................ 54

2.11. Редактирование меню экранной формы............................................................................................................... 56

2.12. Создание нового класса............................................................................................................................................ 58

2.13. Документирование исходного кода в Java.......................................................................................................... 61

2.14. Основные компоненты пакетов swing и awt......................................................................................................... 65

2.15. Технологии Java и .Net............................................................................................................................................... 70

Краткие итоги по главе 2..................................................................................................................................................... 72

Задания..................................................................................................................................................................................... 73

Глава 3. Примитивные типы данных и операторы для работы с ними...................................................................... 74

3.1.Булевский (логический) тип......................................................................................................................................... 74

3.2.Целые типы, переменные, константы........................................................................................................................ 75

3.3.Основные операторы для работы с целочисленными величинами................................................................. 77

3.4.Вещественные типы и класс Math............................................................................................................................. 78

3.5.Правила явного и автоматического преобразования типа при работе с числовыми величинами......... 81

3.6. Оболочечные классы. Упаковка (boxing) и распаковка (unboxing)................................................................. 83

3.7.Приоритет операторов.................................................................................................................................................. 84

3.8.Типы-перечисления (enum).......................................................................................................................................... 85

Краткие итоги по главе 3..................................................................................................................................................... 88

Задания..................................................................................................................................................................................... 89

Глава 4. Работа с числами в языке Java............................................................................................................................... 91

4.1 Двоичное представление целых чисел..................................................................................................................... 91

Позиционные и непозиционные системы счисления.............................................................................................. 91

Двоичное представление положительных целых чисел....................................................................................... 92

Двоичное представление отрицательных целых чисел. Дополнительный код............................................. 93

Проблемы целочисленной машинной арифметики................................................................................................ 94

Шестнадцатеричное представление целых чисел и перевод из одной системы счисления в другую.... 95

4.2. Побитовые маски и сдвиги.......................................................................................................................................... 97

4.3. Двоичное представление вещественных чисел.................................................................................................. 100

Двоичные дроби............................................................................................................................................................. 100

Мантисса и порядок числа......................................................................................................................................... 100

Стандарт IEEE 754 представления чисел в формате с плавающей точкой*............................................... 102

Краткие итоги по главе 4.................................................................................................................................................. 106

Задания.................................................................................................................................................................................. 106

Глава 5. Управляющие конструкции.................................................................................................................................. 108

Составной оператор..................................................................................................................................................... 108

Условный оператор if................................................................................................................................................ 108

Оператор выбора switch.............................................................................................................................................. 112

Условное выражение …?... : ….................................................................................................................................. 112

Операторы инкремента ++ и декремента --............................................................................................................ 113

Оператор цикла for..................................................................................................................................................... 113

Оператор цикла while – цикл с предусловием.................................................................................................. 117

Оператор цикла do...while – цикл с постусловием...................................................................................... 118

Операторы прерывания continue, break, return, System.exit............................................................................... 119

Краткие итоги по главе 5.................................................................................................................................................. 122

Задания.................................................................................................................................................................................. 122

Глава 6. Начальные сведения об объектном программировании.............................................................................. 123

Наследование и полиморфизм. UML-диаграммы...................................................................................................... 123

Функции. Модификаторы. Передача примитивных типов в функции................................................................. 129

Локальные и глобальные переменные. Модификаторы доступа и правила видимости. Ссылка this........ 132

Передача ссылочных типов в функции. Проблема изменения ссылки внутри подпрограммы.................... 134

Наследование. Суперклассы и подклассы. Переопределение методов.............................................................. 139

Наследование и правила видимости. Зарезервированное слово super............................................................... 144

Статическое и динамическое связывание методов. Полиморфизм....................................................................... 146

Базовый класс Object......................................................................................................................................................... 147

Конструкторы. Зарезервированные слова super и this. Блоки инициализации................................................. 149

Удаление неиспользуемых объектов и метод finalize. Проблема деструкторов для сложно устроенных объектов 152

Перегрузка методов............................................................................................................................................................ 152

Правила совместимости ссылочных типов как основа использования полиморфного кода. Приведение и проверка типов.................................................................................................................................................................................................. 155

Рефакторинг.......................................................................................................................................................................... 157

Reverse engineering – построение UML-диаграмм по разработанным классам................................................ 160

Краткие итоги по главе 6.................................................................................................................................................. 166

Задания.................................................................................................................................................................................. 167

Глава 7. Важнейшие объектные типы................................................................................................................................ 169

Массивы................................................................................................................................................................................. 169

Коллекции, списки, итераторы........................................................................................................................................ 173

Работа со строками в Java. Строки как объекты. Классы String, StringBuffer и StringBuilder....................... 176

Работа с графикой............................................................................................................................................................... 180

Исключительные ситуации.............................................................................................................................................. 183

Обработка исключительных ситуаций................................................................................................................... 183

Иерархия исключительных ситуаций...................................................................................................................... 185

Объявление типа исключительной ситуации и оператор throw....................................................................... 186

Объявление метода, который может возбуждать исключительную ситуацию. Зарезервированное слово throws............................................................................................................................................................................................. 187

Работа с файлами и папками........................................................................................................................................... 188

Работа с файлами и папками с помощью объектов типа File............................................................................ 188

Выбор файлов и папок с помощью файлового диалога..................................................................................... 192

Работа с потоками ввода-вывода.............................................................................................................................. 195

Краткие итоги по главе 7.................................................................................................................................................. 202

Задания.................................................................................................................................................................................. 203

Глава 8. Наследование: проблемы и альтернативы. Интерфейсы. Композиция................................................... 204

Проблемы множественного наследования классов. Интерфейсы......................................................................... 204

Отличия интерфейсов от классов. Проблемы наследования интерфейсов........................................................ 206

Пример на использование интерфейсов....................................................................................................................... 208

Композиция как альтернатива множественному наследованию.......................................................................... 210

Краткие итоги по главе 8.................................................................................................................................................. 212

Задания.................................................................................................................................................................................. 212

Глава 9. Дополнительные элементы объектного программирования на языке Java........................................... 214

Потоки выполнения (threads) и синхронизация.......................................................................................................... 214

Преимущества и проблемы при работе с потоками выполнения.................................................................... 214

Синхронизация по ресурсам и событиям............................................................................................................... 215

Класс Thread и интерфейс Runnable. Создание и запуск потока выполнения............................................ 217

Поля и методы, заданные в классе Thread.............................................................................................................. 219

Подключение внешних библиотек DLL.“Родные” (native) методы*.................................................................... 221

Краткие итоги по главе 9.................................................................................................................................................. 224

Задания.................................................................................................................................................................................. 225

Глава 10. Введение в сетевое программирование.......................................................................................................... 227

Краткая справка по языку HTML................................................................................................................................... 227

Апплеты................................................................................................................................................................................. 232

Сервлеты................................................................................................................................................................................ 234

Технология JSP – Java Server Pages................................................................................................................................ 237

Краткие итоги по главе 10................................................................................................................................................ 241

Задания.................................................................................................................................................................................. 242

Глава 11. Встроенные классы.............................................................................................................................................. 243

Виды встроенных классов................................................................................................................................................ 243

Вложенные (nested) классы и интерфейсы................................................................................................................... 243

Внутренние (inner) классы................................................................................................................................................ 244

Локальные (local) классы.................................................................................................................................................. 246

Анонимные (anonimous) классы и обработчики событий....................................................................................... 246

Анонимные (anonimous) классы и слушатели событий (listeners)......................................................................... 247

Краткие итоги по главе 11................................................................................................................................................ 250

Задания.................................................................................................................................................................................. 251

Глава 12. Компонентное программирование................................................................................................................... 252

Компонентная архитектура JavaBeans........................................................................................................................ 252

Мастер создания компонента в NetBeans.................................................................................................................... 253

Пример создания компонента в NetBeans – панель с заголовком......................................................................... 256

Добавление в компонент новых свойств...................................................................................................................... 259

Добавление в компонент новых событий..................................................................................................................... 261

Краткие итоги по главе 12................................................................................................................................................ 265

Задания.................................................................................................................................................................................. 266

Литература................................................................................................................................................................................. 267

Дополнительная литература........................................................................................................................................... 267


Введение

Языку Java посвящены сотни тысяч книг и учебных курсов. Поэтому, без сомнения, предлагаемый курс может рассматриваться только как краткое введение в данную область. Его назначение – дать основные представления о концепциях языка и современном состоянии дел. Java быстро развивается, из-за чего многие прежние представления оказываются устаревшими.

Данный курс основан на лекциях, читавшихся автором студентам кафедры вычислительной физики физического факультета СПбГУ, но был существенно переработан. Курс рассчитан на широкую аудиторию начинающих программистов, от школьников-старшеклассников до студентов старших курсов, а также людей, желающих самостоятельно научиться программировать на этом языке. Кроме того, курс может быть интересен даже опытным программистам, которые по каким-либо причинам не отслеживали изменения и нововведения в Java за последние годы. Курс содержит информацию об основных синтаксических конструкциях языка Java, особенностях и типичных ошибках их использования, а также сведения о современных средах разработки.

Одной из привлекательных особенностей языка Java с самого начала была бесплатность распространения базовых средств разработки (SDK – Software Development Kit) и исполняющей среды Java (виртуальной Java-машины). Однако компилятор, входящий в состав SDK, работал в режиме командной строки, то есть отставал идеологически по крайней мере на 20 лет от современных профессиональных компиляторов. В 2006 году корпорация Sun Microsystems пошла на беспрецедентный шаг – сделала бесплатными профессиональные средства разработки программного обеспечения.

Еще одним шагом Sun в направлении открытости программного обеспечения, в том числе - исходного кода, стала разработка платформы NetBeans. Это среда, основанная на принципах компонентного программирования. Она включает в себя как среду разработки, так и набор библиотечных компонентов ( Beans – “зёрна”. Игра слов: язык Java получил название по имени кофе, которое любили программисты, так что название компонентной модели Java Beans может быть расшифровано как “зёрна кофе Java”). Компонентная модель NetBeans – дальнейший шаг после Java Beans.

Среда разработки NetBeans может быть свободно загружено с сайта Sun и распространяется на условиях лицензии Sun Public License (SPL). Данная лицензия подразумевает, что всё программное обеспечение, написанное на условиях SPL, поставляется с открытым исходным кодом (source code). В настоящее время продукт Sun Java Studio Enterprise прекратил самостоятельное существование и стал расширением среды NetBeans – теперь это NetBeans Enterprise Pack.

Все примеры, приводящиеся в данной книге, разработаны и проверены в среде NetBeans версии 5.5 с JDK1.5.0_04.

Упоминаемые в данной книге названия

Java ® и Solaris ® - являются торговыми марками корпорации Sun Microsystems

Windows® - является торговой маркой корпорации Microsoft

MacOS® - является торговой маркой корпорации Apple

Глава 1. Общие представления о языке Java

1.1. Java и другие языки программирования. Системное и прикладное программирование

Язык программирования Java был создан в рамках проекта корпорации Sun Microsystems по созданию компьютерных программно-аппаратных комплексов нового поколения. Первая версия языка была официально опубликована в 1995 году. С тех пор язык Java стал стандартом де-факто, вытеснив за десять лет языки C и C++ из многих областей программирования. В 1995 году они были абсолютными лидерами, но к 2006 году число программистов, использующих Java, стало заметно превышать число программистов, использующих C и C++, и составляет более четырёх с половиной миллионов человек. А число устройств, в которых используется Java, превышает полтора миллиарда.

Как связаны между собой языки C, C++, JavaScript и Java? Что между ними общего, и в чём они отличаются? В каких случаях следует, а в каких не следует их применять? Для того чтобы ответить на этот вопрос, следует сначала остановиться на особенностях программного обеспечения предыдущих поколений и о современных тенденциях в развитии программного обеспечения.

Первоначально программирование компьютеров шло в машинных кодах. Затем появились языки ASSEMBLER, которые заменили команды процессоров мнемоническими сокращениями, гораздо более удобными для человека, чем последовательности нулей и единиц. Их принято считать языками программирования низкого уровня (то есть близкими к аппаратному уровню), так как они ориентированы на особенности конкретных процессоров. Именно поэтому программы, написанные на языках ASSEMBLER, нельзя было переносить на компьютеры с другим типом процессора - процессоры имели несовместимые наборы команд. То есть они были непереносимы на уровне исходного кода (source code).

Программы, написанные в машинных кодах, то есть в виде последовательности ноликов и единиц, соответствующих командам процессора и необходимым для них данным, нет необходимости как-то преобразовывать. Их можно скопировать в нужное место памяти компьютера и передать управление первой команде программы (задать точку входа в программу).

Программы, написанные на каком-либо языке программирования, сначала надо перевести из одной формы (текстовой) в другую (двоичную, то есть в машинные коды). Процесс такого перевода называется трансляцией (от английского translation – “перевод”, “перемещение”). Не обязательно переводить программу из текстовой формы в двоичные коды, возможен процесс трансляции с одного языка программирования на другой. Или из кодов одного типа процессора в коды другого типа.

Имеется два основных вида трансляции – компиляция и интерпретация .

При компиляции первоначальный набор инструкций однократно переводится в исполняемую форму (машинные коды), и в последующем при работе программы используются только эти коды.

При интерпретации во время каждого вызова необходимых инструкций каждый раз сначала происходит перевод инструкций из одной формы (текстовой или двоичной) в другую – в исполняемые коды процессора используемого компьютера. И только потом эти коды исполняются. Естественно, что интерпретируемые коды исполняются медленнее, чем скомпилированные, так как перевод инструкций из одной формы в другую обычно занимает в несколько раз больше времени чем выполнение полученных инструкций. Но интерпретация обеспечивает большую гибкость по сравнению с компиляцией, и в ряде случаев без неё не обойтись.

В 1956 году появился язык FORTRAN – первый язык программирования высокого уровня (то есть не ориентированный на конкретную аппаратную реализацию компьютера). Он обеспечил переносимость программ на уровне исходных кодов, но довольно дорогой ценой. Во-первых, быстродействие программ, написанных на FORTRAN, было в несколько раз меньше, чем для ассемблерных. Во-вторых, эти программы занимали примерно в два раза больше места в памяти компьютера, чем ассемблерные. И, наконец, пришлось отказаться от поддержки особенностей периферийных устройств – общение с “внешним миром” пришлось ограничить простейшими возможностями, которые в программе одинаково реализовывались для ввода-вывода с помощью перфокарточного считывателя, клавиатуры, принтера, текстового дисплея и т.д. Тем не менее, языки программирования высокого уровня постепенно вытеснили языки ASSEMBLER, поскольку обеспечивали не только переносимость программ, но и гораздо более высокую их надёжность, а также несоизмеримо более высокую скорость разработки сложного программного обеспечения. FORTRAN до сих пор остаётся важнейшим языком программирования для высокопроизводительных численных научных расчётов.

Увеличение аппаратных возможностей компьютеров (количества памяти, быстродействия, появления дисковой памяти большого объёма), а также появление разнообразных периферийных устройств, привело к необходимости пересмотра того, как должны работать программы. Массовый выпуск компьютеров потребовал унификации доступа из программ к различным устройствам. Возникла идея, что из программы можно обращаться к устройству без учёта особенностей его аппаратной реализации. Это возможно, если обращение к устройству идёт не напрямую, а через прилагающуюся программу – драйвер устройства (по-английски driver означает “водитель”). Появились операционные системы - наборы драйверов и программ, распределяющих ресурсы компьютера между разными программами. Соответственно, программное обеспечение стало разделяться на системное и прикладное . Системное программное обеспечение – непосредственно обращающееся к аппаратуре, прикладное – решающее какие-либо прикладные задачи и использующее аппаратные возможности компьютера не напрямую, а через вызовы программ операционной системы. Прикладные программы стали приложениями операционной системы, или, сокращённо, приложениями (applications). Этот термин означает, что программа может работать только под управлением операционной системы. Если на том же компьютере установить другой тип операционной системы, программа-приложение первой операционной системы не будет работать.

Требования к прикладным программам принципиально отличаются от требований к системным программам. От системного программного обеспечения требуется максимальное быстродействие и минимальное количество занимаемых ресурсов, а также возможность доступа к любым необходимым аппаратным ресурсам. От прикладного – максимальная функциональность в конкретной предметной области. При этом быстродействие и занимаемые ресурсы не имеют значения до тех пор, пока не влияют на функциональность. Например, нет совершенно никакой разницы, реагирует программа на нажатие клавиши на клавиатуре за одну десятую или за одну миллионную долю секунды. Правда, на первоначальном этапе создания прикладного программного обеспечения даже прикладные по назначению программы были системными по реализации, так как оказывались вынуждены напрямую обращаться к аппаратуре.

Язык C был создан в 1972 году в одной из исследовательских групп Bell Laboratories при разработке операционной системы Unix. Сначала была предпринята попытка написать операционную систему на ASSEMBLER, но после появления в группе новых компьютеров пришлось создать платформонезависимый язык программирования высокого уровня, с помощью которого можно было бы писать операционные системы. Таким образом, язык C создавался как язык для создания системного программного обеспечения, и таким он остаётся до сих пор. Его идеология и синтаксические конструкции ориентированы на максимальную близость к аппаратному уровню реализации операций – в той степени, в какой он может быть обеспечен на аппаратно-независимом уровне. При этом главным требованием была максимальная скорость работы и минимальное количество занимаемых ресурсов, а также возможность доступа ко всем аппаратным ресурсам. Язык C является языком процедурного программирования , так как его базовыми конструкциями являются подпрограммы . В общем случае подпрограммы принято называть подпрограммами-процедурами (откуда и идёт название “процедурное программирование”) и подпрограммами-функциями. Но в C имеются только подпрограммы-функции. Обычно их называют просто функциями .

Язык C произвёл настоящую революцию в разработке программного обеспечения, получил широкое распространение и стал промышленным стандартом. Он до сих пор применяется для написания операционных систем и программирования микроконтроллеров. Но мало кто в полной мере осознаёт причины его популярности. В чём они заключались? - В том, что он смог обеспечить необходимую функциональность программного обеспечения в условиях низкой производительности компьютеров, крайней ограниченности их ресурсов и неразвитости периферийных устройств! При этом повторилась та же история, что и с FORTRAN, но теперь уже для языка системного программирования. Переход на язык программирования высокого уровня, но с минимальными потерями по производительности и ресурсам, дал большие преимущества.

Большое влияние на развитие теории программирования дал язык PASCAL, разработанный в 1974 году швейцарским профессором Никлаусом Виртом. В данной разработке имелось две части. Первая состояла в собственно языке программирования PASCAL, предназначенном для обучения идеям структурного программирования . Вторая заключалась в идее виртуальной машины. Никлаус Вирт предложил обеспечить переносимость программ, написанных на PASCAL, за счёт компиляции их в набор команд некой абстрактной P-машины (P- сокращение от PASCAL), а не в исполняемый код конкретной аппаратной платформы. А на каждой аппаратной платформе должна была работать программа, интерпретирующая эти коды. Говорят, что такая программа эмулирует (то есть имитирует) систему команд несуществующего процессора. А саму программу называют виртуальной машиной.

В связи с ограниченностью ресурсов компьютеров и отсутствием в PASCAL средств системного программирования этот язык не смог составить конкуренцию языку C, так как практически всё промышленное программирование вплоть до середины последней декады двадцатого века по реализации было системным. Идеи P-машины были в дальнейшем использованы и значительно усовершенствованы в Java.

Развитие теории и практики программирования привело к становлению в 1967-1972 годах нового направления – объектного программирования , основанного на концепциях работы с классами и объектами . Оно обеспечило принципиально новые возможности по сравнению с процедурным. Были предприняты попытки расширения различных языков путём введения в них конструкций объектного программирования. В 1982 году Бьерном Страуструпом путём такого расширения языка C был создан язык, который он назвал “C с классами”. В1983 году после очередных усовершенствований им был создан первый компилятор языка C++. Два плюса означают “C с очень большим количеством добавлений”. C++ является надмножеством над языком C – на нём можно писать программы как на “чистом C”, без использования каких-либо конструкций объектного программирования. В связи с этим, а также дополнительными преимуществами объектного программирования, он быстро приобрёл популярность и стал промышленным стандартом, сначала “де факто”, а потом и “де юре”. Так что в настоящее время C++ является базовым языком системного программирования. Длительное время он использовался и для написания прикладных программ. Но, как мы уже знаем, требования к прикладным программам совпадают к требованиям к системным только в том случае, когда быстродействие компьютера можно рассматривать как низкое, а ресурсы компьютера – малыми. Кроме этого, у языков C и C++ имеется ещё два принципиальных недостатка: а) низкая надёжность как на уровне исходного кода, так и на уровне исполняемого кода; б) отсутствие переносимости на уровне исполняемого кода. С появлением компьютерных сетей эти недостатки стали очень существенным ограничивающим фактором, поскольку вопросы безопасности при работе в локальных, и, особенно, глобальных сетях приобретают первостепенную значимость.

В 1995 году появились сразу два языка программирования, имеющие в настоящее время огромное значение –Java, разработанный в корпорации Sun, и JavaScript, разработанный в небольшой фирме Netscape Communication, получившей к тому времени известность благодаря разработке браузера Netscape Navigator.

Java создавался как универсальный язык, предназначенный для прикладного программирования в неоднородных компьютерных сетях как со стороны клиентского компьютера, так и со стороны сервера. В том числе – для использования на тонких аппаратных клиентах (устройствах малой вычислительной мощности с крайне ограниченными ресурсами). При этом скомпилированные программы Java работают только под управлением виртуальной Java-машины, поэтому они называются приложениями Java . Синтаксис операторов Java практически полностью совпадает с синтаксисом языка C, но, в отличие от C++, Java не является расширением C – это совершенно независимый язык, со своими собственными синтаксическими правилами. Он является гораздо более сильно типизированным по сравнению с C и C++, то есть вносит гораздо больше ограничений на действия с переменными и величинами разных типов. Например, в C/C++ нет разницы между целочисленными числовыми, булевскими и символьными величинами, а также адресами в памяти. То есть, например, можно умножить символ на булевское значение, из которого вычтено целое число, и разделить результат на адрес! В Java введён вполне разумный запрет на почти все действия такого рода.

Язык JavaScript создавался как узкоспециализированный прикладной язык программирования HTML-страниц, расширяющий возможности HTML, и в полной мере отвечает этим потребностям до сих пор. Следует подчеркнуть, что язык JavaScript не имеет никакого отношения к Java. Включение слова “Java” в название JavaScript являлось рекламным трюком фирмы Netscape Communication. Он также C-образен, но, в отличие от Java, является интерпретируемым. Основное назначение JavaScript – программное управление элементами WWW-документов. Языки HTML и XML позволяют задавать статический, неизменный внешний вид документов, и с их помощью невозможно запрограммировать реакцию на действия пользователя. JavaScript позволяет ввести элементы программирования в поведение документа. Программы, написанные на JavaScript, встраиваются в документы в виде исходных кодов (сценариев) и имеют небольшой размер. Для упрощения работы с динамически формируемыми документами JavaScript имеет свободную типизацию – переменные меняют тип по результату присваивания. Поэтому программы, написанные на JavaScript, гораздо менее надёжны, чем написанные на C/C++, не говоря уж про Java.

Java, JavaScript и C++ являются объектно-ориентированными языками программирования, и все они имеют C-образный синтаксис операторов. Но как объектные модели, так и базовые конструкции этих языков (за исключением синтаксиса операторов), в этих языках принципиально различны. Ни один из них не является версией или упрощением другого – это совсем разные языки, предназначенные для разных целей. Итак, Java- универсальный язык прикладного программирования, JavaScript – узкоспециализированный язык программирования HTML-документов, C++ - универсальный язык системного программирования.

В 2000 году в корпорации Microsoft была разработана платформа .Net (читается “дотнет”, DotNet– в переводе с английского “точка Net” ). Она стала альтернативой платформе Java и во многом повторяла её идеи. Основное различие заключалось в том, что для этой платформы можно использовать произвольное количество языков программирования, а не один. Причём классы .Net оказываются совместимы как в целях наследования, так и по исполняемому коду независимо от языка, используемого для их создания. Важнейшим языком .Net стал Java-образный язык C# (читается “Си шарп”). Фактически, C# унаследовал от Java большинство особенностей - динамическую объектную модель, сборку “мусора”, основные синтаксические конструкции. Хотя и является вполне самостоятельным языком программирования, имеющим много привлекательных черт. В частности, компонентные модели Java и C# принципиально отличаются.

Java стал первым универсальным C-образным языком прикладного программирования, что обеспечило лёгкость перехода на этот язык большого числа программистов, знакомых с C и C++. А наличие средств строгой проверки типов, ориентация на работу с компьютерными сетями, переносимость на уровне исполняемого кода и поддержка платформонезависимого графического интерфейса, а также запрет прямого обращения к аппаратуре обеспечили выполнение большинства требований, предъявлявшихся к языку прикладного программирования. Чем больше становятся быстродействие и объём памяти компьютеров, тем больше потребность в разделении прикладного и системного программного обеспечения. Соответственно, для прикладных программ исчезает необходимость напрямую обращаться к памяти и другим аппаратным устройствам компьютера. Поэтому среди прикладных программ с каждым годом растёт доля программного обеспечения, написанного на Java и языках .Net. Но как по числу программистов, так и по числу устройств, использующих соответствующие платформы, Java в настоящее время лидирует с большим отрывом.

1.2. Виртуальная Java-машина, байт-код, JIT-компиляция. Категории программ, написанных на языке Java

Первоначально слово “программа” означало последовательность инструкций процессора для решения какой-либо задачи. Эти инструкции являлись машинными кодами, и разницы между исходным и исполняемым кодом программы не было. Разница появилась, когда программы стали писать на языках программирования. При этом программой стали называть как текст, содержащийся в файле с исходным кодом, так и исполняемый файл.

Для устранения неоднозначности термина “программа”, исполняемый код программы принято называть приложением (application). Термин “приложение” – сокращение от фразы “приложение операционной системы”. Он означает, что исполняемый код программы может работать только под управлением соответствующей операционной системы. Работа под управлением операционной системы позволяет избежать зависимости программы от устройства конкретного варианта аппаратуры на компьютере, где она должна выполняться. Например, как автору программы, так и пользователю совершенно безразлично, как устроено устройство, с которого считывается информация – будет ли это жёсткий диск с одной, двумя или шестнадцатью считывающих головок. Или это будет CD-привод, DVD-привод или ещё какой-либо другой тип носителя. Но переносимость обычных приложений ограничивается одним типом операционных систем. Например, приложение MS Windows® не будет работать под Linux, и наоборот. Программы, написанные на языке Java, выполняются под управлением специальной программы -виртуальной Java-машины, и поэтому обладают переносимостью на любую операционную систему, где имеется соответствующая Java-машина. Благодаря этому они являются не приложениями какой-либо операционной системы, а приложениями Java .

Программы, написанные на языке Java, представляют из себя наборы классов и сохраняются в текстовых файлах с расширением .java. (Про то, что такое классы, будет рассказано несколько позже). При компиляции текст программы переводится (транслируются) в двоичные файлы с расширением .class. Такие файлы содержат байт-код - инструкции для абстрактного Java-процессора в виде байтовых последовательностей команд этого процессора и данных к ним. Для того, чтобы байт-код был выполнен на каком-либо компьютере, он должен быть переведён в инструкции для соответствующего процессора. Именно этим и занимается Java-машина. Первоначально байт-код всегда интерпретировался: каждый раз, как встречалась какая-либо инструкция Java-процессора, она переводилась в последовательность инструкций процессора компьютера. Естественно, это значительно замедляло работу приложений Java.

В настоящее время используется более сложная схема, называемая JIT-компиляцией (Jast-In-Time) – компиляцией “по ходу дела”, “налету”. Когда какая-либо инструкция (или набор инструкций) Java-процессора выполняется в первый раз, происходит компиляция соответствующего ей байт-кода с сохранением скомпилированного кода в специальном буфере. При последующем вызове той же инструкции вместо её интерпретации происходит вызов из буфера скомпилированного кода. Поэтому интерпретация происходит только при первом вызове инструкции.

Сложные оптимизирующие JIT-компиляторы действуют ещё изощрённей. Поскольку обычно компиляция инструкции идёт гораздо дольше по сравнению с интерпретацией этой инструкции, время её выполнения в первый раз при наличии JIT-компиляции может заметно отличаться в худшую сторону по сравнению с чистой интерпретацией. Поэтому бывает выгоднее сначала запустить процесс интерпретации, а параллельно ему в фоновом режиме компилировать инструкцию. Только после окончания процесса компиляции при последующих вызовах инструкции будет исполняться её скомпилированный код. – До этого все её вызовы будут интерпретироваться. Разработанная Sun виртуальная машина HotSpot осуществляет JIT-компиляцию только тех участков байт-кода, которые критичны к времени выполнения программы. При этом по ходу работы программы происходит оптимизация скомпилированного кода.

Благодаря компиляции программ Java в платформонезависимый байт-код обеспечивается переносимость этих программ не только на уровне исходного кода, но и на уровне скомпилированных приложений. Конечно, при этом на компьютере, где выполняется приложение, должна быть установлена программа виртуальной Java-машины (Java Virtual Machine - JVM), скомпилированная в коды соответствующего процессора (native code – “родной” код). На одном и том же компьютере может быть установлено несколько Java-машин разных версий или от разных производителей. Спецификация Java-машины является открытой, точно так же, как требования к компилятору языка Java. Поэтому различные фирмы, а не только Sun, разрабатывают компиляторы Java и Java-машины.

Приложение операционной системы запускается с помощью средств операционной системы. Приложение Java, напротив, запускается с помощью виртуальной Java-машины, которая сама является приложением операционной системы. Таким образом, сначала стартует Java-машина. Она получает в качестве параметра имя файла с компилированным кодом класса. В этом классе ищется и запускается на выполнение подпрограмма с именем main.

Приложения Java обладают не только хорошей переносимостью, но и высокой скоростью работы. Однако даже при наличии JIT-компиляции они всё-таки могут выполняться медленнее, чем программы, написанные на C или C++. Это связано с тем, что JIT-компиляция создаёт не такой оптимальный код как многопроходный компилятор C/C++, который может тратить очень большое время и много ресурсов на отыскивание конструкций программы, которые можно оптимизировать. А JIT-компиляция происходит “на лету”, в условиях жёсткой ограниченности времени и ресурсов. Для решения этой проблемы были разработаны компиляторы программ Java в код конкретных программно-аппаратных платформ (native code – “родной” код). Например, свободно распространяемый фондом GNU компилятор gjc. Правда, заметные успехи Sun в усовершенствовании Java-машины позволили практически достичь, а в ряде случаев даже обогнать по быстродействию программы, написанные на других языках. В частности, приложения Java, активно занимающиеся выделением-высвобождением памяти, работают быстрее своих аналогов, написанных на C/C++, благодаря специальному механизму программных слотов памяти (slot – “паз, отверстие для вставления чего-либо”).

Виртуальная Java-машина не только исполняет байт-код (интерпретирует его, занимается JIT-компиляцией и исполняет JIT-компилированный код), но и выполняет ряд других функций. Например, взаимодействует с операционной системой, обеспечивая доступ к файлам или поддержку графики. А также обеспечивает автоматическое высвобождение памяти, занятой ненужными объектами – так называемую сборку мусора (garbage collection).

Программы Java можно разделить на несколько основных категорий:

· Приложение (application) – аналог “обычной” прикладной программы.

· Апплет (applet) – специализированная программа с ограниченными возможностями, работающая в окне WWW-документа под управлением браузера.

· Сервлет (servlet) - специализированная программа с ограниченными возможностями, работающая в WWW на стороне сервера. Используется преимущественно в рамках технологии JSP (Java Server Pages - Серверных Страниц Java) для программирования WWW-документов со стороны сервера.

· Серверное приложение (Enterprise application) – предназначено для многократного использования на стороне сервера.

· Библиотека (Java Class Library – библиотека классов, либо NetBeans Module – модуль платформы NetBeans) – предназначена для многократного использования программами Java

Между приложениями и апплетами Java имеется принципиальное различие: приложение запускается непосредственно с компьютера пользователя и имеет доступ ко всем ресурсам компьютера наравне с любыми другими программами. Апплет же загружается из WWW с постороннего сервера, причём из-за самой идеологии WWW сайт, с которого загружен апплет, в общем случае не может быть признан надёжным. А сам апплет имеет возможность передавать данные на произвольный сервер в WWW. Поэтому для того, чтобы избежать риска утечки конфиденциальной информации с компьютера пользователя или совершения враждебных действий у апплетов убраны многие возможности, имеющиеся у приложений.

Сервлеты – это приложения Java , запускаемые со стороны сервера. Они имеют возможности доступа к файловой системе и другим ресурсам сервера через набор управляющих конструкций, предопределённых в рамках технологии JSP и пакета javax.servlet. Технология JSP заключается в наличии дополнительных конструкций в HTML- или XML-документах, которые позволяют осуществлять вызовы сценариев (“скриптов”), написанных на языке Java. В результате удаётся очень просто и удобно осуществлять обработку данных или элементов документа, и внедрять в нужные места документа результаты обработки. Сценарии Java перед первым выполнением автоматически компилируются на стороне сервера, поэтому выполняемый код выполняется достаточно быстро. Но, конечно, требует, чтобы была установлена соответствующая Java-машина. Например, входящая в состав Sun Application Server – программного обеспечения, обеспечивающего поддержку большого количества необходимых серверных возможностей для работы в WWW. Отметим, что Sun Application Server также распространяется бесплатно и входит в комплект NetBeans Enterprise Pack.

Первоначально Java позиционировался Sun как язык, обеспечивающий развитые графические возможности WWW-документов благодаря включению в них апплетов. Однако в настоящее время основными областями использования Java является прикладное программирование на основе приложений, страниц JSP и сервлетов, а также других видов серверных программ. При этом использование апплетов играет незначительную роль.

Виртуальную Java-машину часто называют исполняющей средой (Java Runtime Environment - JRE).

Существует два основных способа установки Java-машины на клиентский компьютер:

· JRE из поставки Software Development Kit (SDK) - Комплекта разработки программного обеспечения.

· Специализированный вариант JRE в составе Интернет-браузера, называющийся Java plugin.

Комплект последних версий SDK можно свободно загружать с сайта Sun http://java.sun.com/ .

При использовании апплетов требуется, чтобы в состав браузера входил специализированный комплект JRE. Как правило, он поставляется вместе с браузером, и может при необходимости обновляться. Для MS Internet Explorer такой комплект и его обновления могут быть свободно загружены с сайта Microsoft.

Имеется возможность установки Java-машины от различных производителей, не обязательно устанавливать комплект SDK от Sun. На одном и том же компьютере может быть установлено сразу несколько различных Java-машин, в том числе комплекты SDK разных версий. Правда, опыт показывает, что при этом некоторые программы, написанные на Java, теряют работоспособность (частично или полностью).

Комплекты SDK имеют классификацию, опирающуюся на версию Java (языка программирования и, соответственно, Java-машины) и тип создаваемых приложений. Так, ко времени написания данного текста выходили версии SDK 1.0, 1.1, 1.2, 1.3, 1.4, 1.5 и 1.6. У каждой версии имеется ряд подверсий, не сопровождающихся изменением языка программирования, а связанных в основном с исправлением ошибок или внесением небольших изменений в библиотеки. Например, 1.4.1_01 или 1.5.0_04.

Версии Java 1.0 и 1.1 принято называть Java 1. Все версии Java начиная c 1.2 называют Java 2. Однако более надёжно классифицировать по номеру SDK, так как язык Java для версии SDK 1.5 очень заметно отличается по возможностям от языка Java для более ранних версий SDK – в него добавлено большое количество новых синтаксических конструкций, а также изменён ряд правил. Поэтому код, правильный в Java для версии SDK 1.5, может оказаться неправильным в Java для версии SDK 1.4. Не говоря уж про Java для версии SDK 1.3 или 1.2. Кроме того, недавно компания Sun перестала использовать в названиях комплектов программного обеспечения термин Java 2 и происходящие от него сокращения вида j2.

Комплекты разработки SDK одной версии отличаются по типу создаваемых с их помощью приложений. Имеется три типа SDK:

· Java ME – комплект Java Micro Edition (микро-издание) http://java.sun.com/j2me/, предназначенный для программирования “тонких аппаратных клиентов”. То есть устройств, обладающих малыми ресурсами - наладонных компьютеров, сотовых телефонов, микроконтроллеров, смарт-карт. Старое название J2ME.

· Java SE – комплект Java Standard Edition (стандартное издание) http://java.sun.com/j2se/, предназначенный для программирования “толстых клиентов”. То есть устройств, обладающих достаточно большими ресурсами - обычных компьютеров. Старое название J2SE.

· Java EE– комплект Java Enterprise Edition http://java.sun.com/j2ee/, предназначенный для написания серверного программного обеспечения. Старое название J2EE.

При распространении какого-либо продукта, написанного на Java, возможна установка только программного обеспечения Java-машины (JRE – Java Runtime Environment). Например, в случае использования Java 1.4.1_01 - комплекта j2re1.4.1_01. При этом создаётся папка с именем j2re1.4.1_01 с вложенными папками bin и lib. В папке bin содержатся файлы и папки, необходимые для работы Java-машины и дополнительных инструментов для работы с ней в специальных режимах. В папке lib содержатся вспомогательные файлы и библиотеки, в основном связанные с параметрами настроек системы.

Также возможна установка целиком SDK. Например, при установке SDK Java SE 1.5.0_04 создаётся папка JDK1.5.0_04 с вложенными папками bin, demo, include, jre, lib, sample, а также архивом src.zip с исходными кодами стандартных классов Java. В папке bin содержатся файлы инструментов разработки, в папке demo - файлы примеров с исходными кодами. В папке include - заголовки файлов C для доступа к ряду библиотек Java и отладчику виртуальной Java-машины на платформо-зависимом уровне - на основе интерфейсов JNI (Java Native Interface) и JVMDI (Java Virtual Machine Debugging Interface), соответственно. В папке jre находятся файлы, необходимые для работы с виртуальной Java-машиной. Папка lib содержит ряд библиотек и сопроводительных файлов, необходимых для работы инструментов из папки bin. В папке sample находятся примеры с исходными кодами.

Аббревиатура JDK расшифровывается как Java Development Kit – комплект разработки программного обеспечения на Java. К сожалению, в комплекте отсутствует даже самая простейшая документация с описанием назначения имеющихся в нём инструментов – даны ссылки на сайт компании Sun, где можно найти эту информацию. Поэтому перечислим назначение основных инструментов. Они делятся на несколько категорий.

Средства разработки приложений

Утилита

Назначение

javac

Компилятор в режиме командной строки для программ, написанных на языке Java

java

Утилита для запуска в режиме командной строки откомпилированных программ-приложений

appletviewer

Утилита для запуска на исполнение и отладку апплетов без браузера. При этом не гарантируется работоспособность отлаженного апплета в браузере.

jdb

Отладчик программ, написанных на языке Java

javadoc

Генератор документации по классом на основе комментариев, начинающихся с /**

jar

Создание и управление Java-архивами jar

javah

Генератор заголовочных файлов C/C++ для подключения к программам Java внешних библиотек C/C++ на основе интерфейса JNI

javap

Дизассемблер классов

extcheck

Утилита для обнаружения конфликтов между файлами архивов jar

native2ascii

Утилита для конвертации в режиме командной строки параметра, передаваемого в виде текста на национальном алфавите, в последовательность символов UNICODE.

Кроме этого, имеются средства поддержки работы в WWW и корпоративных сетях (интранет) с интерфейсом RMI - интерфейсом удалённого вызова методов. Это программы rmic, rmiregistry, rmid. Также имеются средства поддержки информационной безопасности keytool, jarsigner, policytool, и ряд файлов других категорий утилит.

Подчеркнём, что набор утилит JDK рассчитан на морально устаревший режим командной строки, и что гораздо удобнее и правильнее пользоваться современной профессиональной средой разработки NetBeans. Для её работы из JDK необходим только комплект JRE.

1.3.Алфавит языка Java. Десятичные и шестнадцатеричные цифры и целые числа. Зарезервированные слова

Алфавит языка Java

Алфавит языка Java состоит из букв, десятичных цифр и специальных символов. Буквами считаются латинские буквы (кодируются в стандарте ASCII), буквы национальных алфавитов (кодируются в стандарте Unicode, кодировка UTF-16), а также соответствующие им символы, кодируемые управляющими последовательностями (о них будет рассказано чуть позже).

Буквы и цифры можно использовать в качестве идентификаторов (т.е. имён) переменных, методов и других элементов языка программирования. Правда, при использовании в идентификаторах национальных алфавитов в ряде случаев могут возникнуть проблемы – эти символы будут показываться в виде вопросительных знаков.

Как буквы рассматривается только часть символов национальных алфавитов. Остальные символы национальных алфавитов - это специальные символы. Они используются в качестве операторов и разделителей языка Java и не могут входить в состав идентификаторов.

Латинские буквы ASCII

ABCD...XYZ - заглавные (прописные) ,

abcd...xyz – строчные

Дополнительные “буквы” ASCII

_ - знак подчеркивания,

$ - знак доллара.

Национальные буквы на примере русского алфавита

АБВГ…ЭЮЯ - заглавные (прописные),

абвг…эюя – строчные

Десятичные цифры

0 1 2 3 4 5 6 7 8 9

Десятичные и шестнадцатеричные цифры и целые числа

Целые числовые константы в исходном коде Java (так называемые литерные константы) могут быть десятичными или шестнадцатеричными. Они записываются либо символами ASCII, или символами Unicode следующим образом.

Десятичные константы записываются как обычно. Например, -137.

Шестнадцатеричная константа начинается с символов 0x или 0X (цифра 0, после которой следует латинская буква X), а затем идёт само число в шестнадцатеричной нотации. Например, 0x10 соответствует 1016 =16; 0x2F соответствует 2F16 =47, и т.д. О шестнадцатеричной нотации рассказано чуть ниже.

Ранее иногда применялись восьмеричные числа, и в языках C/C++, а также старых версиях Java можно было их записывать в виде числа, начинающегося с цифры 0. То есть 010 означало 108 =8. В настоящее время в программировании восьмеричные числа практически никогда не применяются, а неадекватное использование ведущего нуля может приводить к логическим ошибкам в программе.

Целая константа в обычной записи имеет тип int. Если после константы добавить букву L (или l, что хуже видно в тексте, хотя в среде разработки выделяется цветом), она будет иметь тип long, обладающий более широким диапазоном значений, чем тип int.

Поясним теперь, что такое шестнадцатеричная нотация записи чисел и зачем она нужна.

Информация представляется в компьютере в двоичном виде – как последовательность бит. Бит – это минимальная порция информации, он может быть представлен в виде ячейки, в которой хранится или ноль, или единица. Но бит – слишком мелкая единица, поэтому в компьютерах информация хранится, кодируется и передаётся байтами - порциями по 8 бит.

В данной книге под “ячейкой памяти” будет пониматься непрерывная область памяти (с последовательно идущими адресами), выделенная программой для хранения данных. На рисунках мы будем изображать ячейку прямоугольником, внутри которого находятся хранящиеся в ячейке данные. Если у ячейки имеется имя, оно будет писаться рядом с этим прямоугольником.

Мы привыкли работать с числами, записанными в так называемой десятичной системе счисления. В ней имеется 10 цифр (от 0 до 9), а в числе имеются десятичные разряды . Каждый разряд слева имеет вес 10 по сравнению с предыдущим, то есть для получения значения числа, соответствующего цифре в каком-то разряде, стоящую в нём цифру надо умножать на 10 в соответствующей степени. То есть 52=5∙10+2, 137=1∙102 +3∙101 +7, и т.п.

В программировании десятичной системой счисления пользоваться не всегда удобно, так как в компьютерах информация организована в виде бит, байт и более крупных порций. Человеку неудобно оперировать данными в виде длинных последовательностей нулей и единиц. В настоящее время в программировании стандартной является шестнадцатеричная система записи чисел. Например, с её помощью естественным образом кодируется цвет, устанавливаются значения отдельных бит числа, осуществляется шифрование и дешифрование информации, и так далее. В этой системе счисления всё очень похоже на десятичную, но только не 10, а 16 цифр, и вес разряда не 10, а 16. В качестве первых 10 цифр используются обычные десятичные цифры, а в качестве недостающих цифр, больших 9, используются заглавные латинские буквы A, B, C, D, E, F:

0 1 2 3 4 5 6 7 8 9 A B C D E F

То есть A=10, B=11, C=12, D=13, E=14, F=15.

Заметим, что в шестнадцатеричной системе счисления числа от 0 до 9 записываются одинаково, а превышающие 9 отличаются. Для чисел от 10 до 15 в шестнадцатеричной системе счисления используются буквы от A до F, после чего происходит использование следующего шестнадцатеричного разряда. Десятичное число 16 в шестнадцатеричной системе счисления записывается как 10. Для того, чтобы не путать числа, записанные в разных системах счисления, около них справа пишут индекс с указанием основания системы счисления. Для десятичной системы счисления это 10, для шестнадцатеричной 16. Для десятичной системы основание обычно не указывают, если это не приводит к путанице. Точно так же в технической литературе часто не указывают основание для чисел, записанных в шестнадцатеричной системе счисления, если в записи числа встречаются не только “обычные” цифры от 0 до 9, но и “буквенные” цифры от A до F. Обычно используют заглавные буквы, но можно применять и строчные.

Рассмотрим примеры.

0x10 = 1016 =16 ;

0x100 = 10016 =16 ∙16=256;

0x1000 = 100016 =(16)3 =4096;

0x20 = 2016 =2∙16 =32;

0x21 = 2116 =2∙16 +1=33;

0xF = F16 =15 ;

0x1F = 1F16 =1∙16 +15=31 ;

0x2F = 2F16 =2∙16 +15=47 ;

0xFF = FF16 =15 ∙16+15=255;

Более подробно вопросы представления чисел в компьютере будут рассмотрены в отдельном разделе.

Зарезервированные слова языка Java

Это слова, зарезервированные для синтаксических конструкций языка, причём их назначение нельзя переопределять внутри программы.

abstract

boolean

break

byte

case

catch

char

class

const

continue

default

do

double

else

enum

extends

false

final

finally

float

for

goto

if

implements

import

instanceof

int

interface

long

native

new

null

package

private

protected

public

return

short

static

super

switch

synchronized

this

throw

throws

transient

true

try

void

volatile

while

Их нельзя использовать в качестве идентификаторов (имён переменных, подпрограмм и т.п.), но можно использовать в строковых выражениях.

1.4. Управляющие последовательности. Символы Unicode. Специальные символы

Управляющие последовательности

Управляющие последовательности - символы формирования текста

Иногда в тексте программы в строковых константах требуется использовать символы, которые обычным образом в текст программы ввести нельзя. Например, символы кавычек (их надо использовать внутри кавычек, что затруднительно), символ вопроса (зарезервирован для тернарного условного оператора), а также различные специальные символы. В этом случае используют управляющую последовательность – символ обратной косой черты, после которой следует один управляющий символ. В таблице приведены управляющие последовательности, применяющиеся в языке Java.

Символ

Что означает

\a

звонок

\b

возврат на один символ назад

\f

перевод на новую страницу

\n

перевод на новую строку

\r

возврат к началу строки

\t

горизонтальная табуляция

\v

вертикальная табуляция

\’

кавычка

\”

двойные кавычки

\\

обратная косая черта

\?

вопросительный знак

\u

начало кодировки символа Unicode

Управляющие последовательности – символы Unicode

Управляющая последовательность может содержать несколько символов. Например, символы национальных алфавитов могут кодироваться последовательностью “\u”, после которой идёт код символа в шестнадцатеричной кодировке для кодовых таблиц UTF-16 или UTF-8. Например:

\u0030 - \u0039 – цифры ISO-LATIN от 0 до 9

\u0024 – знак доллара $

\u0041 - \u005a – буквы от A до Z

\u0061 - \u007a – буквы от a до z

Простые специальные символы

+

Оператор сложения

.

Точка – десятичный разделитель в числовом литерном выражении; разделитель в составном имени для доступа к элементу пакета, класса, объекта, интерфейса

Оператор вычитания

(

Левая круглая скобка – используется для открытия списка параметров в операторах и для открытия группируемой части в выражениях

*

Оператор умножения

)

Правая круглая скобка– используется для закрытия списка параметров в операторах и для закрытия группируемой части в выражениях

/

Оператор деления

[

Левая квадратная скобка – открытие индекса массива

%

Оператор остатка от целочисленного деления

]

Правая квадратная скобка – закрытие индекса массива

=

Оператор присваивания

;

Точка с запятой – окончание оператора

~

Оператор побитового дополнения (побитовое “не”)

'

Апостроф (одиночная кавычка) – открытие и закрытие символа

?

Вопросительный знак – часть тернарного (состоящего из трёх частей) условного оператора “? :”

Двойные кавычки – открытие и закрытие строки символов

:

Двоеточие – часть условного оператора “? :”. Также используется для задания метки – ставится после имени метки.

\

обратная косая черта (backslash) – используется для задания управляющих последовательностей символов

^

Оператор “исключающее или” (XOR)

знак пробела (невидимый)

&

Оператор “побитовое и” (AND)

знак табуляции (невидимый)

|

Оператор “побитовое или” (OR)

@

Коммерческое a (“эт”) – знак начала метаданных

!

Оператор “НЕ”

#

- не имеет специального назначения

>

Больше

¤

- не имеет специального назначения

<

Меньше

«

- не имеет специального назначения

{

Левая фигурная скобка – открытие блока кода

»

- не имеет специального назначения

}

Правая фигурная скобка – закрытие блока кода

- не имеет специального назначения

,

Запятая - разделитель в списке параметров оператора; разделитель в составном операторе

§

- не имеет специального назначения

Составные специальные символы

Символ

Что означает

++

Оператор инкремента (увеличения на 1); x++ эквивалентно x=x+1

--

Оператор декремента (уменьшения на 1); x-- эквивалентно x=x-1

&&

Оператор “логическое И” (AND)

||

Оператор “ логическое ИЛИ” (OR)

<<

Оператор левого побитового сдвига

>>>

Оператор беззнакового правого побитового сдвига

>>

Оператор правого побитового сдвига с сохранением знака отрицательного числа

==

Равно

! =

не равно

+=

y+=x эквивалентно y=y+x

-=

y-=x эквивалентно y=y-x

*=

y*=x эквивалентно y=y*x

/=

y/=x эквивалентно y=y/x

%=

y%=x эквивалентно y=y%x

|=

y|=x эквивалентно y=y|x

^=

y^=x эквивалентно y=y^x

>>=

y>>=x эквивалентно y= y>>x

>>>=

y>>>=x эквивалентно y= y>>>x

<<=

y<<=x эквивалентно y= y<<x

/*

Начало многострочного комментария.

/**

Начало многострочного комментария, предназначенного для автоматического создания документации по классу.

*/

Конец многострочного комментария (открываемого как /* или /**).

//

Однострочный комментарий.

1.5.Идентификаторы. Переменные и типы . Примитивные и ссылочные типы

Идентификаторы - это имена переменных, подпрограмм-функций и других элементов языка программирования. В идентификаторах можно применять только буквы и цифры, причём первой всегда должна быть буква (в том числе символы подчёркивания и доллара), а далее может идти произвольная комбинация букв и цифр. Некоторые символы национальных алфавитов рассматриваются как буквы, и их можно применять в идентификаторах. Но некоторые используются в качестве символов-разделителей, и в идентификаторах их использовать нельзя.

Язык Java является регистро-чувствительным . Это значит, что идентификаторы чувствительны к тому, в каком регистре (верхнем или нижнем) набираются символы. Например, имена i1 и I1 соответствуют разным идентификаторам. Это правило привычно для тех, кто изучал языки C/C++, но может на первых порах вызвать сложности у тех, кто изучал язык PASCAL, который является регистро-нечувствительным.

Длина идентификатора в Java любая, по крайней мере, в пределах разумного. Так, даже при длине идентификатора во всю ширину экрана компилятор NetBeans правильно работает.

Переменная – это именованная ячейка памяти, содержимое которой может изменяться. Перед тем, как использовать какую-либо переменную, она должна быть задана в области программы, предшествующей месту, где эта переменная используется. При объявлении переменной сначала указывается тип переменной, а затем идентификатор задаваемой переменной. Указание типа позволяет компилятору задавать размер ячейки (объём памяти, выделяемой под переменную или значение данного типа), а также допустимые правила действий с переменными и значениями этого типа. В Java существует ряд предопределённых типов: int – целое число, float – вещественное число, boolean – логическое значение, Object – самый простой объектный тип (класс) Java, и т.д. Также имеется возможность задавать собственные объектные типы (классы), о чём будет рассказано позже.

Объявление переменных a1 и b1, имеющих некий тип MyType1, осуществляется так:

MyType1 a1,b1;

При этом MyType1 – имя типа этих переменных.

Другой пример – объявление переменной j типа int :

int j;

Типы бывают предопределённые и пользовательские. Например, int – предопределённый тип, а MyType1– пользовательский. Для объявления переменной не требуется никакого зарезервированного слова, а имя типа пишется перед именами задаваемых переменных.

Объявление переменных может сопровождаться их инициализацией - присваиванием начальных значений. Приведём пример такого объявления целочисленных переменных i1 и i2 :

int i1=5;

int i2=-78;

либо

int i1=5,i2=-78;

Присваивания вида int i1=i2=5;, характерные для C/C++, запрещены.

Для начинающих программистов отметим, что символ “=” используется в Java и многих других языках в качестве символа присваивания , а не символа равенства, как это принято в математике. Он означает, что значение, стоящее с правой стороны от этого символа, копируется в переменную, стоящую в левой части. То есть, например, присваивание b =a означает, что в переменную (ячейку) с именем b надо скопировать значение из переменной (ячейки) с именем a . Поэтому неправильное с точки зрения математики выражение

x=x+1

в программировании вполне корректно. Оно означает, что надо взять значение, хранящееся в ячейке с именем x , прибавить к нему 1 (это будет происходить где-то вне ячейки x ), после чего получившийся результат записать в ячейку x , заменив им прежнее значение.

После объявления переменных они могут быть использованы в выражениях и присваиваниях:

переменная=значение;

переменная=выражение;

переменная1= переменная2;

и так далее. Например,

i1=i2+5*i1;

Примитивными типами называются такие, для которых данные содержатся в одной ячейке памяти, и эта ячейка не имеет подъячеек.

Ссылочными типами называются такие, для которых в ячейке памяти (ссылочной переменной ) содержатся не сами данные, а только адреса этих данных, то есть ссылки на данные. При присваивании в ссылочную переменную заносится новый адрес, а не сами данные. Но непосредственного доступа к адресу, хранящемуся в ссылочных переменных, нет. Это сделано для обеспечения безопасности работы с данными – как с точки зрения устранения непреднамеренных ошибок, характерных для работы с данными по их адресам в языках C/C++/PASCAL, так и для устранения возможности намеренного взлома информации.

Если ссылочной переменной не присвоено ссылки, в ней хранится нулевой адрес, которому дано символическое имя null. Ссылки можно присваивать друг другу, если они совместимы по типам, а также присваивать значение null. При этом из одной ссылочной переменной в другую копируется адрес. Ссылочные переменные можно сравнивать на равенство, в том числе на равенство null. При этом сравниваются не данные, а их адреса, хранящиеся в ссылочных переменных.

В Java все типы делятся на примитивные и ссылочные. К примитивным типам относятся следующие предопределённые типы: целочисленные типы byte,short,int, long, char, типы данных в формате с плавающей точкой float, double, а также булевский (логический) тип boolean и типы-перечисления, объявляемые с помощью зарезервированного слова enum (сокращение от enumeration – “перечисление”). Все остальные типы Java являются ссылочными.

В Java действуют следующие соглашения о регистре букв в идентификаторах:

· Имена примитивных типов следует писать в нижнем регистре (строчными буквами). Например, int, float, boolean и т.д.

· Имена ссылочных типов следует начинать с заглавной (большой) буквы, а далее для имён, состоящих из одного слова, писать все остальные буквы в нижнем регистре. Например, Object, Float, Boolean, Collection, Runnable. Но если имя составное, новую часть имени начинают с заглавной буквы. Например, JButton, JTextField, JFormattedTextField, MyType и т.д. Обратите внимание, что типы float и Float, boolean и Boolean различны – язык Java чувствителен к регистру букв!

· Для переменных и методов имена, состоящие из одного слова, следует писать в нижнем регистре. Например, i, j, object1. Если имя составное, новую часть имени начинают с заглавной буквы: myVariable, jButton2, jTextField2.getText() и т.д.

· Имена констант следует писать в верхнем регистре (большими буквами), разделяя входящие в имя составные части символом подчёркивания “_”. Например, Double.MIN_VALUE, Double.MAX_VALUE , JOptionPane.INFORMATION_MESSAGE, MY_CHARS_COUNT и т.п.

· Символ подчёркивания “_” рекомендуется использовать для разделения составных частей имени только в именах констант и пакетов.

Переменная примитивного типа может быть отождествлена с ячейкой, в которой хранятся данные. У неё всегда есть имя. Присваивание переменной примитивного типа меняет значение данных. Для ссылочных переменных действия производятся с адресами ячеек, в которых хранятся данные, а не с самими данными.

Для чего нужны такие усложнения? Ведь человеку гораздо естественнее работать с ячейками памяти, в которых хранятся данные, а не адреса этих данных. Ответ заключается в том, что в программах часто требуются динамически создаваемые и уничтожаемые данные. Для них нельзя заранее создать необходимое число переменных, так как это число неизвестно на этапе написания программы и зависит от выбора пользователя. Такие данные приходится помещать в динамически создаваемые и уничтожаемые ячейки. А с этими ячейками удаётся работать только с помощью ссылочных переменных.

Ссылочные типы Java используются в объектном программировании. В частности, для работы со строками, файлами, элементами пользовательского интерфейса. Все пользовательские типы (задаваемые программистом) , кроме типов-перечислений, являются ссылочными. В том числе – строковые типы.


Краткие итоги по главе 1

- Алфавит языка Java состоит из букв, десятичных цифр и специальных символов. Буквами считаются латинские буквы (кодируются в стандарте ASCII), буквы национальных алфавитов (кодируются в стандарте Unicode), а также соответствующие им символы, кодируемые управляющими последовательностями.

- В программах разрешается пользоваться десятичными и шестнадцатеричными целыми числовыми константами. Шестнадцатеричная константа начинается с символов 0x или 0X, после чего идёт само число в шестнадцатеричной нотации.

- Java - универсальный язык прикладного программирования, JavaScript – узкоспециализированный язык программирования HTML-документов, C++ - универсальный язык системного программирования. Java - компилируемый, платформонезависимый, объектно-ориентированный язык с C-образным синтаксисом.

- Программы Java переносимы как на уровне исходных кодов, так и на уровне скомпилированных исполняемых кодов – байт-кода. Байт-код является платформонезависимым, так как не содержит инструкций процессора конкретного компьютера. Он интерпретируется виртуальной Java-машиной (JVM).

- JIT-компиляция (Jast-In-Time) – компиляция байт-кода в код конкретной платформы в момент выполнения программы, то есть “по ходу дела”, “налету”. Она позволяет ускорить работу программ за счёт замены интерпретации байт-кода на выполнение скомпилированного кода.

- Основные категории программ Java:

· Приложение (application) – аналог “обычной” прикладной программы.

· Апплет (applet) – специализированная программа, работающая в окне WWW-документа под управлением браузера.

· Сервлет (servlet) - специализированная программа, работающая в WWW на стороне сервера

· Модуль EJB (Enterprise JavaBeans) – предназначен для многократного использования серверными приложениями Java

· Библиотека – предназначена для многократного использования программами классов Java

- Версии Java 1.0 и 1.1 принято называть Java 1. Все версии Java начиная c 1.2 принято называть Java 2.

- Поставить на компьютер исполняющую среду Java (виртуальную Java-машину) можно путём установки SDK (Software Development Kit) - Комплекта разработки программного обеспечения. Имеется три типа SDK:

· Java ME – комплект Java Micro Edition, предназначенный для программирования “тонких аппаратных клиентов”.

· Java SE – комплект Java Standard Edition, предназначенный для программирования обычных компьютеров.

· Java EE– комплект Java Enterprise Edition, предназначенный для написания серверного программного обеспечения.

- Язык Java является регистро-чувствительным. Исходные коды программ Java набираются в виде последовательности символов Unicode.

- Управляющая последовательность применяется в случае, когда требуется использовать символ, который обычным образом в текст программы ввести нельзя. Простая управляющая последовательность начинается с символа “\”, после которого идёт управляющий символ. Управляющая последовательность для кодирования символа Unicode начинается с последовательности из двух символов -“\u”, после которой следует четыре цифры номера символа в шестнадцатеричной нотации. Например, \u1234 .

- Специальные символы используются в качестве операторов и разделителей языка Java и не могут входить в состав идентификаторов. Специальные символы бывают простые и составные. Они используются в операторах, для форматирования текста и как разделители.

- Идентификаторы - это имена переменных, процедур, функций и т.д. В идентификаторах можно применять только буквы и цифры, причём первой всегда должна быть буква, а далее может идти произвольная комбинация букв и цифр. Длина идентификатора в Java любая.

- Переменная – это именованная ячейка памяти, содержимое которой может изменяться. При объявлении переменной сначала указывается тип переменной, а затем идентификатор задаваемой переменной.

- Типы в Java делятся на примитивные и ссылочные. Существует несколько предопределённых примитивных типов, все остальные – ссылочные. Все пользовательские типы кроме типов-перечислений являются ссылочными. Значение null соответствует ссылочной переменной, которой не назначен адрес ячейки с данными.

Типичные ошибки:

- Путают языки Java и JavaScript, либо считают, что JavaScript – это интерпретируемый вариант Java. Хотя эти языки не имеют друг к другу никакого отношения.

- Ошибочно считают, что приложение Java может быть запущено на любом компьютере без установки исполняющей среды (JRE).

- Не различают приложения (applications) и апплеты (applets).

- При записи шестнадцатеричного числа вида 0x… вместо ведущего нуля пишут букву O.

- Ошибочно считают, что в идентификаторах Java нельзя использовать символы национальных алфавитов.

- Ошибочно считают, что не имеет значения, в каком регистре набраны символы идентификатора (характерно для тех, кто раньше программировал на PASCAL или FORTRAN).

Задания

· Написать в 16-ричном виде числа 0, 1, 8, 15, 16, 255, 256.

· Дать ответ, являются ли допустимыми идентификаторами i1, i_1, 1i, i&1, i1234567891011, IJKLMN ?

· Являются ли допустимыми и различными идентификаторы myObject, MyObject, myobject, Myobject, my object, my_object ?

Глава 2. Объектно-ориентированное проектирование и плат форма NetBeans

2.1.Процедурное и объектно-ориентированное программирование. Инкапсуляция

Объектно-ориентированное программирование (ООП) - это методология программирования, опирающаяся на три базовых принципа:

- инкапсуляцию ,

- наследование ,

- полиморфизм .

Язык Java является объектно-ориентированным и в полном объёме использует эти принципы. В данном параграфе рассматривается принцип инкапсуляции, наследованию и полиморфизму посвящены отдельные параграфы.

Построение программ, основанных на ООП, принципиально отличается от более ранней методики процедурного программирования , в которой основой построения программы служили подпрограммы .

Программа – это набор инструкций процессору и данных, объединённых в единую функционально законченную последовательность, позволяющую выполнять какую-нибудь конкретную деятельность.

Подпрограмма – это набор инструкций и данных, объединённых в относительно самостоятельную последовательность, позволяющую выполнять какую-нибудь конкретную деятельность внутри программы. При этом подпрограмма не может работать самостоятельно - она запускается из программы, и может получать из неё данные или передавать их в программу.

Подпрограммы принято делить на подпрограммы-процедуры и подпрограммы-функции. Подпрограммы-процедуры вызываются для выполнения каких-либо действий, например – распечатки текста на принтере. Подпрограммы-функции выполняют какие-либо действия и возвращают некоторое значение. Например, проводится последовательность действий по вычислению синуса, и возвращается вычисленное значение. Или создаётся сложно устроенный объект и возвращается ссылка на него (адрес ячейки, в которой он находится).

Программы, написанные в соответствии с принципами процедурного программирования, состоят из набора подпрограмм, причём для решения конкретной задачи программист явно указывает на каждом шагу, что делать и как делать. Эти программы практически полностью (процентов на девяносто) состоят из решения конкретных задач.

Программы, написанные в соответствии с принципами ООП, пишутся совершенно иначе. В них основное время занимает продумывание и описание того, как устроены классы. Код с описанием классов предназначен для многократного использования без внесения каких-либо изменений. И только небольшая часть времени посвящается решению конкретной задачи – написания такого кода с использованием классов, который в других задачах такого типа не применить. Именно благодаря такому подходу объектное программирование приобрело огромную популярность – при необходимости решения сходных задач можно использовать уже готовый код, модифицировав только ту часть программы, которая относится к решению конкретной задачи.

Подробный разбор принципов ООП будет дан позже. Пока же в общих чертах разъясним их суть.

Самым простым из указанных в начале параграфа принципов является инкапсуляция . Это слово в общем случае означает “заключение внутрь капсулы”. То есть ограничение доступа к внутреннему содержимому снаружи и отсутствие такого ограничения внутри капсулы. В объектном программировании “инкапсуляция” означает использование классов – таких типов , в которых кроме данных описаны подпрограммы, позволяющие работать с этими данными, а также выполнять другие действия. Такие подпрограммы, инкапсулированные в класс, называются методами . Поля данных и методы, заданные в классе, часто называют членами класса (class members).

Класс – это описание того, как будет устроен объект , являющийся экземпляром данного класса , а также какие методы объект может вызывать. Заметим, что методы, в отличие от других подпрограмм, могут напрямую обращаться к данным своего объекта. Так как экземплярами классов (“воплощением” в реальность того, что описано в классе) являются объекты, классы называют объектными типами .

Все объекты, являющиеся экземплярами некоторого класса, имеют одинаковые наборы полей данных (атрибуты объекта) – но со значениями этих данных, которые свои для каждого объекта. Поля данных это переменные, заданные на уровне описания класса, а не при описании метода. В процессе жизни объекта эти значения могут изменяться. Значения полей данных объекта задают его состояние . А методы задают поведение объекта. Причём в общем случае на это поведение влияет состояние объекта – методы пользуются значениями его полей данных.

Классы в Java задаются следующим образом. Сначала пишется зарезервированное слово class, затем имя класса, после чего в фигурных скобках пишется реализация класса – задаются его поля (глобальные переменные ) и методы.

Объектные переменные – такие переменные, которые имеют объектный тип. В Java объектные переменные – это не сами объекты, а только ссылки на них. То есть все объектные типы являются ссылочными.

Объявление объектной переменной осуществляется так же, как и для других типов переменных. Сначала пишется тип, а затем через пробел имя объявляемой переменной.

Например, если мы задаём переменную obj1 типа Circle, “окружность”, её задание осуществляется так :

Circle obj1;

Связывание объектной переменной с объектом осуществляется путём присваивания. В правой части присваивания можно указать либо функцию, возвращающую ссылку на объект (адрес объекта), либо имя другой объектной переменной. Если объектной переменной не присвоено ссылки, в ней хранится значение null. Объектные переменные можно сравнивать на равенство, в том числе на равенство null. При этом сравниваются не сами объекты, а их адреса, хранящиеся в объектных переменных.

Создаётся объект с помощью вызова специальной подпрограммы, задаваемой в классе и называемой конструктором . Конструктор возвращает ссылку на созданный объект. Имя конструктора в Java всегда совпадает с именем класса , экземпляр которого создаётся. Перед именем конструктора во время вызова ставится оператор new – “новый”, означающий, что создаётся новый объект. Например, вызов

obj1=new Circle();

означает, что создаётся новый объект типа Circle, “окружность”, и ссылка на него (адрес объекта) записывается в переменную obj1. Переменная obj1 до этого уже должна быть объявлена. Оператор new отвечает за динамическое выделение памяти под создаваемый объект.

Часто совмещают задание объектной переменной и назначение ей объекта. В нашем случае оно будет выглядеть как

Circle obj1=new Circle();

У конструктора, как и у любой подпрограммы, может быть список параметров. Они нужны для того, чтобы задать начальное состояние объекта при его создании. Например, мы хотим, чтобы у создаваемой окружности можно было при вызове конструктора задать координаты x, y её центра и радиус r. Тогда при написании класса Circle можно предусмотреть конструктор, в котором первым параметром задаётся координата x, вторым – y, третьим – радиус окружности r. Тогда задание переменной obj1 может выглядеть так:

Circle obj1=new Circle(130,120,50);

Оно означает, что создаётся объект-окружность, имеющий центр в точке с координатами x=130, y=120, и у которой радиус r=50.

Если разработчики класса не создали ни одного конструктора, в реализации класса автоматически создаётся конструктор по умолчанию, имеющий пустой список параметров. И его можно вызывать в программе так, как мы это первоначально делали для класса Circle.

Отметим ещё одно правило, касающееся используемых имён. Как мы помним, имена объектных типов принято писать с заглавной буквы, а имена объектных переменных – с маленькой. Если объектная переменная имеет тип Circle, она служит ссылкой на объекты-окружности. Поэтому имя obj1 не очень удачно – мы используем его только для того, чтобы подчеркнуть, что именно с помощью этой переменной осуществляется связь с объектом, и чтобы читатель не путал тип переменной, её имя и имя конструктора. В Java принято называть объектные переменные так же, как их типы, но начинать имя со строчной буквы. Поэтому предыдущий оператор мог бы выглядеть так:

Circle circle=new Circle(130,120,50);

Если требуется работа с несколькими объектными переменными одного типа, их принято называть в соответствии с указанным выше правилом, но добавлять порядковый номер. Следующие строки программного кода создают два независимых объекта с одинаковыми начальными параметрами:

Circle circle1=new Circle(130,120,50);

Circle circle2=new Circle(130,120,50);

С помощью объектных переменных осуществляется доступ к полям данных или методам объекта: сначала указывается имя переменной, затем точка, после чего пишется имя поля данных или метода. Например, если имя объектной переменной obj1, а имя целочисленного поля данных x, то присваивание ему нового значения будет выглядеть как

obj1.x=5;

А если имя подпрограммы show, у неё нет параметров и она не возвращает никакого значения, то её вызов будет выглядеть как

obj1.show();

Методы делятся на методы объектов и методы классов . Чаще всего пользуются методами объектов. Они так называются потому, что пользуются полями данных объектов, и поэтому их можно вызывать только из самих объектов. Методы классов, напротив, не пользуются полями данных объектов, и могут работать при отсутствии объекта. Поэтому их можно вызывать как из классов, так и из объектов. Формат вызова: имяКласса.имяМетода(список параметров) или имяОбъекта. имяМетода(список параметров) .

При задании метода класса перед его именем необходимо поставить модификатор static – “статический”. Это крайне неудачное название, пришедшее в язык Java из C++. Мы никогда не будем называть такие методы статическими, а будем называть их методами класса, как это принято в теории программирования.

Точно так же переменные (поля данных) делятся на переменные объектов и переменные классов . При задании переменной класса перед её именем необходимо поставить модификатор static. Переменные класса, как и методы класса, можно вызывать как из классов, так и из объектов. Формат вызова: имяКласса.имяПеременной или имяОбъекта.имяПеременной .

Не следует путать классы, объекты и объектные переменные. Класс – это тип, то есть описание того, как устроена ячейка памяти, в которой будут располагаться поля данных объекта. Объект – это содержимое данной ячейки памяти. А в переменной объектного типа содержится адрес объекта, то есть адрес ячейки памяти. Сказанное относится только к языкам с динамической объектной моделью, каким, в частности, является Java. В C++ это не так.

Как уже было сказано, кроме полей данных в классе описываются методы. Несмотря на схожесть задания в классе полей и методов их реальное размещение во время работы программы отличается. Методы не хранятся в объектах, но объекты могут их вызывать. Каждый объект имеет свой комплект полей данных – “носит свои данные с собой”. Если имеется сотня объектов одного типа, то есть являющихся экземплярами одного и того же класса, в памяти компьютера будет иметься сотня ячеек памяти, устроенных так, как это описано в классе. Причём у каждого объекта значения этих данных могут быть свои. Например, если объект является окружностью, отрисовываемой на экране, у каждой окружности будет свой набор координат, радиусов и цветов. Если мы будем отрисовывать окружности с помощью метода show(), нет необходимости в каждом объекте хранить код этого метода – он для всех ста объектов будет одним и тем же. Поэтому методы не хранятся в объектах – они хранятся в классах. Класс – более общая сущность, чем объект, и до того, как во время работы программы в памяти компьютера будет создан объект, сначала должен быть загружен в память соответствующий ему класс. В Java имеется возможность создавать переменные типа “класс”, и с их помощью обращаться к классам таким образом, как будто это объекты особого рода. Но, в отличие от обычных объектов, такие “объекты” не могут существовать в нескольких экземплярах, и правила работы с ними принципиально отличаются от работы с объектами. Такие сущности называются метаобъектами .

Объявление переменных может осуществляться либо в классе, либо в методе. В первом случае мы будем говорить, что переменная является полем данных объекта, или глобальной переменной. Во втором – что она является локаль ной переменной.

2.2. Работа со ссылочными переменными. Сборка мусора

Объекты, как мы уже знаем, являются экземплярами ссылочных типов. Работа со ссылочными переменными имеет специфику, принципиально отличающую её от работы с переменными примитивного типа. В каждой переменной примитивного типа содержится своё значение, и изменение этого значения не влияет на те значения, которые можно получить с помощью других переменных. Причём имя переменной примитивного типа можно рассматривать как имя ячейки с данными, и у такой ячейки может быть только одно имя, которое не может меняться по ходу работы программы. Для ссылочных переменных это не так.

Переменные ссылочного типа содержат адреса данных, а не сами данные. Поэтому присваивания для таких переменных меняют адреса, но не данные. Кроме того, из-за этого под них выделяется одинаковое количество памяти независимо от типа объектов, на которые они ссылаются. А имена ссылочных переменных можно рассматривать как псевдонимы имён ячеек с данными – у одной и той же ячейки с данными может быть сколько угодно псевдонимов, так как адрес одной и той же ячейки можно копировать в произвольное число переменных соответствующего типа. И все они будут ссылаться на одну и ту же ячейку с данными.

В Java ссылочные переменные используются для работы с объектами: в этом языке программирования используется динамическая объектная модель , и все объекты создаются динамически, с явным указанием в программе момента их создания. Это отличает Java от C++, языка со статической объектной моделью . В C++ могут существовать как статически заданные объекты, так и динамически создаваемые. Но это не преимущество, как могло бы показаться, а проблема, так как в ряде случаев создаёт принципиально неразрешимые ситуации.

Следует отметить, что сами объекты безымянны, и доступ к ним осуществляется только через ссылочные переменные. Часто говорят про ссылочную переменную как про сам объект, поскольку долго и неудобно произносить “объект, на который ссылается данная переменная”. Но этого по мере возможности следует избегать.

Ссылочной переменной любого типа может быть присвоено значение null, означающее, что она никуда не ссылается. Попытка доступа к объекту через такую переменную вызовет ошибку. В Java все ссылочные переменные первоначально инициируются значением null, если им не назначена ссылка на объект прямо в месте объявления. Очень часто встречающаяся ошибка – попытка доступа к полю или методу с помощью ссылочной переменной, которой не сопоставлен объект. Такая ошибка не может быть обнаружена на этапе компиляции и является ошибкой времени выполнения (Run-time error). При этом приложение Java генерирует исключительную ситуацию (ошибку) попытки доступа к объекту через ссылку null с сообщением следующего вида:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException.

Последовательность действий со ссылочными переменными и объектами удобно описывать с помощью рисунков, на которых каждой такой переменной и каждому объекту сопоставлен прямоугольник – символическое изображение ячейки. Около ячейки пишется её имя, если оно есть, а внутри – значение, содержащееся в ячейке.

Объект


Ссылочная переменная

Если переменная является ссылочной, из неё выходит стрелочка-ссылка. Она кончается на том объекте, на который указывает ссылка. Если в ссылочной переменной содержится значение null (ссылка “в никуда”, адрес==0), рисуется “висящая” короткая стрелка, у которой находится надпись “null”. Отметим, что в Java символом равенства является “==”, а не символ “=”, который используется для оператора присваивания.

Если ссылка перещёлкивается, то либо создаётся новый рисунок (в книжке), либо перечёркивается крестиком прежняя стрелочка и рисуется новая (на листе бумаги или на доске). При новом перещёлкивании эта “старая” стрелка перечёркивается двумя крестиками, а “более свежая”, которая была перещёлкнута – одним крестиком, и так далее. Такая система обозначений позволяет наглядно представить, что происходит при работе со ссылками, и не запутаться в том, куда они указывают и с какими ссылками в какой момент связаны динамически создаваемые объекты.

При выполнении оператора new , после которого указан вызов конструктора, динамически выделяется новая безымянная ячейка памяти, имеющая тип, соответствующий типу конструктора, а сам конструктор после окончания работы возвращает адрес этой ячейки. Если у нас в левой части присваивания стоит ссылочная переменная, то в результате ссылка “перещёлкивается” на динамически созданную ячейку.

Рассмотрим этот процесс подробнее. Будем считать, что сначала в ячейке circle1 типа Circle хранится нулевой адрес (значение ссылки равно null). Будем изображать это как стрелку в никуда с надписью null.

Переменная

circle1 типа Circle


null

После оператора

circle1=new Circle(x1,y1,r1) ;

в динамически выделенной безымянной ячейке памяти будет создан объект-окружность с координатами центра x1, y1 и радиусом r1 (это какие-то значения, конкретная величина которых в данном случае не имеет значения):

Объект1 типа Circle


circle1

Адрес


Поля объекта доступны через ссылку как по чтению, так и по записи. До тех пор, пока ссылочная переменная circle1 содержит адрес Объекта1, имя circle1 является псевдонимом, заменяющим имя этого объекта. Его можно использовать так же, как имя обычной переменной в любых выражениях и операторах, не связанных с изменением адреса в переменной circle1.

Поскольку между ссылочными переменными одного типа разрешены присваивания, переменная по ходу программы может сменить объект, на который она ссылается. Если circle2 также имеет тип Circle, то допустимы присваивания вида

circle2= circle1;

Такие присваивания изменяют адреса в ячейках ссылочных переменных, но не меняют содержания объектов.

Рассмотрим следующий участок кода:

Circle circle1=new Circle(x1,y1,r1) ;

Circle circle2=new Circle(x2,y2,r2) ;

Circle circle3;

Ему соответствует следующий рисунок:

Объект1 типа Circle


circle1

Адрес1

Объект2 типа Circle


circle2

Адрес2


circle3

Адрес==0


null

Проведём присваивание

circle3=circle2;

В результате получится такая картинка:

Объект1 типа Circle


circle1

Адрес1

Объект2 типа Circle


circle2

Адрес2


circle3

Адрес2


Обе переменные, как circle2, так и circle3, теперь ссылаются на один и тот же объект – в них находится один и тот же Адрес2. То есть оба имени – синоним имени Объекта2. Напомним, что сам объект, как все динамически создаваемые величины, безымянный. Таким образом, circle2.x даст значение x2, точно так же, как и circle3.x. Более того, если мы изменим значение circle2.x, это приведёт к изменению circle3.x – ведь это одно и то же поле x нашего Объекта2.

Рассмотрим теперь, что произойдёт при присваивании

circle1=circle2;

Этот случай отличается от предыдущего только тем, что переменная circle1 до присваивания уже была связана с объектом.

Объект1 типа Circle

x==x1

y==y1

r==r1


circle1

Адрес2

Объект2 типа Circle


circle2

Адрес2


circle3

Адрес2


В результате у Объекта2 окажется сразу три ссылочные переменные, которые с ним связаны, и имена которых являются его псевдонимами в данном месте программы: circle1, circle2 и circle3. При этом программная связь с Объектом1 окажется утеряна – он занимает место в памяти компьютера, но программный доступ к нему невозможен, поскольку адрес этого объекта программой утерян. Таким образом, он является бесполезным и напрасно занимает ресурсы компьютера.

Про такие ячейки памяти говорят, что они являются мусором . В Java предусмотрен механизм высвобождения памяти, занятой такими бесполезными объектами. Он называется сборкой мусора (garbage collection) и работает автоматически. Этим в фоновом режиме занимается специальная часть виртуальной Java-машины, сборщик мусора . При программировании на Java, отличие от таких языков как C/C++ или Object PASCAL, программисту нет необходимости самому заботиться о высвобождении памяти, занятой под динамически создаваемые объекты.

Следует подчеркнуть, что намеренная потеря связи ссылочной переменной с ненужным уже объектом – это одно, а непреднамеренная – совсем другое. Если вы не планировали потерю связи с объектом, а она произошла, это логическая ошибка. И хотя она не приведёт к зависанию программы или её неожиданному закрытию, такая программа будет работать не так, как вы предполагали, то есть неправильно или не совсем правильно. Что иногда ещё опасней, так как ошибку можно не заметить или, если заметили, очень трудно понять её причину.

2.3. Проекты NetBeans. Пакеты. Уровни видимости классов. Импорт классов

Современное программное обеспечение построено по модульному (блочному) принципу. Программы давно перестали состоять из одного файла. Поэтому вместо слова “программа” лучше употреблять слово “проект”. Тем более что термин “программа”, как уже говорилось, неоднозначен.

Идеология Java подразумевает работу в компьютерных сетях и возможность подгрузки в необходимый момент через сеть требуемых классов и ресурсов, в которых нуждается программа, и которые не были до того загружены. Для обеспечения такого рода работы приложения Java разрабатываются и распространяются в виде большого числа независимых классов. Однако такой способ разработки приводит к чрезвычайно высокой фрагментации программы. Даже небольшие учебные проекты часто состоят из десятков классов, а реальные проекты – из сотен. При этом каждому общедоступному (public) классу соответствует свой файл, имеющий то же имя. Для того чтобы справиться с таким обилием файлов, в Java предусмотрено специальное средство группировки классов, называемое пакетом (package). Пакеты обеспечивают независимые пространства имён (namespaces), а также ограничение доступа к классам.

Классы всегда задаются в каком-либо пакете. Пакеты могут быть вложенными с произвольным уровнем вложения (ограничивается только операционной системой и, как правило, не менее 256). Каждому пакету соответствует папка с исходными кодами соответствующих классов, при этом пакету, вложенному в другой, соответствует папка, вложенная в другую.

Для того чтобы поместить класс в пакет, требуется продекларировать имя пакета в начале файла, в котором объявлен класс, в виде

package имя_пакета;

Кроме того, необходимо поместить исходный код класса в папку, соответствующую пакету.

Если декларация имени пакета отсутствует, считается, что класс принадлежит пакету с именем default.

Вложенным пакетам соответствуют составные имена. Например, если мы имеем пакет с именем pkg1, в который вложен пакет с именем pkg2, в который вложен пакет с именем pkg3, то объявление, что класс с именем MyClass1 находится в пакете pkg3, будет выглядеть как

package pkg1.pkg2.pkg3;

class MyClass1 {

….

}

Внутри фигурных скобок должно содержатся описание класса. Оно заменено многоточием.

В качестве разделителя имён пакетов в программе используется точка независимо от типа операционной системы. Хотя в разных операционных системах вложенность папок будет обозначаться по-разному:

в MS Windows ® : pkg1\pkg2\pkg3\

в Unix и Linux : pkg1/pkg2/pkg3/

в Mac OS : pkg1:pkg2:pkg3:

При создании проекта в среде NetBeans помещение класса в пакет происходит автоматически.

При декларации класса можно указывать, что он общедоступен, с помощью модификатора доступа public:

public class MyClass2 {

….

}

В этом случае возможен доступ к данному классу из других пакетов.

Если же модификатор public отсутствует, как в случае MyClass1, то доступ к классу разрешён только из классов, находящихся с ним в одном пакете. Про такие файлы говорят, что у них пакетный вариант доступа (в C++ аналогичный вид доступа называется “дружественным” - friend).

В файле .java можно располагать только один общедоступный класс и произвольное число классов с пакетным уровнем видимости.

Класс может использовать общедоступные (public) классы из других пакетов напрямую, с указанием полного имени класса в пространстве имён, включающего имя пакета. Например, доступ к классу MyClass2 в таком варианте осуществляется как

pkg1.pkg2.pkg3.MyClass2

Для того, чтобы задать переменную объектного типа, надо до того указать её класс. В нашем случае это будет выглядеть так:

pkg1.pkg2.pkg3.MyClass2 myObject;

Для того чтобы отличать имена классов от имён пакетов, в Java принято имена пакетов писать только строчными буквами, имена классов начинать с заглавной буквы, а имена полей данных (в том числе имена объектных переменных) и методов начинать со строчной буквы. Если имя класса, поля данных или метода (но не пакета!) состоит из нескольких слов, каждое новое слово принято или писать с заглавной буквы. Новое слово также можно отделять от предыдущего символом подчёркивания. Таким образом, из названия javax.swing.JMenuItem понятно, что javax и swing – пакеты, а JMenuItem – имя класса.

Существует способ доступа к именам из другого пакета “напрямую”, без указания каждый раз полного пути в пространстве имён. Это делается с помощью оператора import. Если мы хотим импортировать имя класса MyClass2 из пакета pkg3, то после объявления имени нашего пакета (например, mypack1), но до объявления нашего класса (например, MyClass3) пишется

import pkg1.pkg2.pkg3.MyClass2;

При этом в классе MyClass3 имя MyClass2 можно использовать напрямую, без указания перед ним имени пакета pkg1.pkg2.pkg3. При этом задание переменной будет выглядеть так:

MyClass2 myObject;

Но если мы импортируем пакеты, содержащие классы с одинаковыми именами, требуется указание полного имени класса – квалифицированного именем пакета.

Если мы хотим импортировать имена всех классов из пакета, в операторе import после имени пакета вместо имени класса следует написать * . Пример:

import pkg1.pkg2.pkg3.*;

Заметим, что импортируются только имена файлов, находящихся точно на уровне указанного пакета. Импорта имён из вложенных в него пакетов не происходит. Например, если записать import pkg1.*; или import pkg1.pkg2.*; , то имя класса MyClass2 не будет импортировано, так как хотя он и находится внутри pkg1 и pkg2, но не непосредственно, а в пакете pkg3.

Имеется одно исключение из правила для импорта: классы ядра языка Java, содержащиеся в пакете java.lang, импортируются автоматически без указания имени пакета.

Пример: объявление графического объекта g, имеющего тип , может проводиться тремя способами.

Во-первых, напрямую, с указанием имени пакета и класса:

java.awt.Graphics g;

Во-вторых, с предварительным импортом класса Graphics из пакета java.awt и последующим указанием имени этого класса без его спецификации именем пакета:

import java.awt.Graphics;

Graphics g;

В-третьих, с предварительным импортом всех классов (в том числе Graphics) из пакета java.awt и последующим указанием имени этого класса без его спецификации именем пакета:

import java.awt.*;

Graphics g;

2.4. Базовые пакеты и классы Java

В пакете java находятся следующие пакеты и классы:

Пакет, класс

Краткое описание

java.applet

Поддержка работы с апплетами.

java.awt

Базовый пакет работы с графическим пользовательским интерфейсом (Abstract Window Toolkit - Абстрактный Инструментарий графического Окна).

java.beens

Поддержка компонентной модели JavaBeans.

java.io

Поддержка базовых средств ввода-вывода.

java.lang

Содержит базовые классы языка Java. Автоматически импортируется в любую программу без указания имени пакета.

java.lang.reflect

Поддерживает механизм доступа к классам как метаобъектам, обеспечивающий возможность динамического выяснения программой, какие возможности поддерживает класс. Данный механизм называется reflection - “отражение”.

java.lang.Math

Класс, обеспечивающий поддержку основных математических функций, а также простейшее средство генерации псевдослучайных чисел.

java.math

Поддержка вычислений с целыми числами произвольной длины, а также числами в формате с плавающей точкой произвольной точности.

java.net

Поддержка работы в Интернет, а также соединений через сокеты (sockets).

java.nio

Содержит классы и пакеты для поддержки сетевых соединений, расширяющие возможности пакета java.io . В частности, содержит классы контейнеров (буферов) для создания списков с данными различных примитивных типов, а также пакеты channels (“каналы соединения, коннекции”) и charset (“национальный набор символов”). Пакет charset обеспечивает поддержку перекодирования из символов Unicode в последовательность байт для передачи через канал связи, а также обратное преобразование.

java.rmi

Поддержка вызовов удалённых методов.

java.security

Поддержка специальных средств, обеспечивающих безопасность приложения, в том числе при работе в компьютерных сетях (списки доступа, сертификаты безопасности, шифрование и т.д.).

java.sql

Поддержка SQL-запросов к базам данных.

java.text

Поддержка специальных средств, обеспечивающих локализацию программ – классы, обеспечивающие настройки для работы с текстом, датами, текстовым представлением чисел. Кроме того, содержит средства для зависимого от локализации сравнения строк.

java.util

Содержит важнейшие классы для работы со структурами данных (в том числе – необходимых для работы с событиями и датами). В частности – поддержку работы с массивами (сортировка, поиск), а также расширенные средства генерации псевдослучайных чисел.

java.util.jar

Поддержка работы с jar-архивами (базовым видом архивов в Java).

java.util.zip

Поддержка работы с zip-архивами.

Пакет javax обеспечивает поддержку новых возможностей, введённых в Java 2. В нём находятся следующие пакеты:

Пакет, класс

Краткое описание

javax.accessibility

Обеспечивает настройку специальных возможностей представления информации для людей с плохим зрением, слухом и т.п., а также других случаев, когда требуется специализированный доступ для управления информационными объектами.

javax.activity

Вспомогательный пакет для работы с компонентами.

javax.crypto

Поддержка шифрования-расшифровки данных.

javax.imageio

Поддержка работы с изображениями (ввод-вывод).

javax.management

Поддержка работы с управляющими компонентами (MBean – Management Bean).

javax.naming

Поддержка работы с пространством имён компонентов.

javax.net

Поддержка работы в Интернет, а также соединений через сокеты (sockets). – Расширение возможностей java.net

javax.print

Поддержка работы с печатью документов.

javax.rmi

Поддержка вызовов удалённых методов. – Расширение возможностей java.rmi

javax.security

Поддержка специальных средств, обеспечивающих безопасность приложения. – Расширение возможностей java.security

javax.sound

Поддержка работы со звуковыми потоками и файлами.

javax.sql

Поддержка SQL-запросов к базам данных. – Расширение возможностей java.sql

javax.swing

Библиотека основных графических компонентов в Java 2.

javax.transaction

Поддержка работы с транзакциями.

javax.xml

Поддержка работы с XML документами и парсерами.

Пакет com.sun от фирмы Sun Microsystems в основном обеспечивает расширение возможностей пакета javax. В нём находятся следующие пакеты:

Пакет, класс

Краткое описание

com.sun.accessibility

Дополнение к пакету javax.accessibility

com.sun.beans

Дополнение к пакету java.beens

com.sun.corba

Поддержка работы в компьютерных сетях с базами данных по технологии CORBA (Common Object Request Broker Architecture).

com.sun.crypto

Дополнение к пакету javax.crypto

com.sun.image

Поддержка работы с изображениями

com.sun.imageio

Дополнение к пакету javax.imageio

com.sun.java

Поддержка стилей показа приложений (см.раздел “Внешний вид приложения”), а также служебные утилиты для работы с браузерами и WWW-документами.

com.sun.java_cup

Поддержка технологии JavaCup

com.sun.jlex

Поддержка работы лексического анализатора.

com.sun.jmx

Дополнение к пакету javax.management

com.sun.jndi

Пакет в процессе разработки.

com.sun.management

Дополнение к пакету javax.management

com.sun.media

Поддержка работы со звуком.

com.sun.naming

Дополнение к пакету javax.naming

com.sun.net

Дополнение к пакету javax.net

com.sun.org

Поддержка взаимодействия с сервером Apache, средства работы с базами данных по технологии CORBA.

com.sun.rmi

Дополнение к пакету javax.rmi

В пакете org находятся следующие пакеты, предоставляемые свободным сообществом разработчиков:

Пакет, класс

Краткое описание

org.ietf

Поддержка защищенных соединений по протоколу GSS (Kerberos v5 ).

org.jdesktop

Менеджер размещения GroupLayout.

org.omg

Средства для использования из программ на Java технологии CORBA, применяемой для создания распределенных объектных приложений.

org.w3c

Интерфейсы для работы с XML-документами в соответствии со спецификацией DOM.

org.xml

Поддержка работы с XML-документами.

2.5. Создание в NetBeans простейшего приложения Java

Создадим с помощью среды NetBeans приложение Java. Для этого запустим интегрированную среду разработки (IDE) NetBeans , и выберем в главном меню File/New Project… В открывшемся диалоге выберем General / Java Application / Next>

Создание нового проекта. Шаг 1.

После чего можно нажимать кнопку Finish – значения по умолчанию для начала менять не стоит. Это можно будет делать потом, когда вы освоитесь со средой разработки.

Создание нового проекта. Шаг 2.

На следующем рисунке показано, как выглядит редактирование исходного кода приложения в среде NetBeans.

В левом верхнем окне “Projects” показывается дерево проектов. В нашем случае это дерево для проекта JavaApplication1. Это окно может быть использовано для одновременного показа произвольного числа проектов. По умолчанию все деревья свёрнуты, и нужные узлы следует разворачивать щелчком по узлу с “плюсиком” или двойным щелчком по соответствующему имени.

В правом окне “Source” показывается исходный код проекта.

В левом нижнем окне “Navigator” показывается список имён членов класса приложения – имена переменных и подпрограмм. Двойной щелчок по имени приводит к тому, что в окне редактора исходного кода происходит переход на то место, где задана соответствующая переменная или подпрограмма.

Редактирование исходного кода приложения

Рассмотрим, как выглядит сгенерированный исходный код нашего приложения Java:

/*

* Main.java

*

* Created on 21 Июнь 2006 г., 13:08

*

* To change this template, choose Tools | Template Manager

* and open the template in the editor.

*/

package javaapplication1;

/**

*

* @author User

*/

public class Main {

/** Creates a new instance of Main */

public Main() {

}

/**

* @param args the command line arguments

*/

public static void main(String[] args) {

// TODO code application logic here

}

}

Сначала идёт многострочный комментарий /* … */ Он содержит информацию об имени класса и времени его создания.

Затем объявляется, что наш класс будет находиться в пакете javaapplication1.

После этого идёт многострочный комментарий /** … */ , предназначенный для автоматического создания документации по классу. В нём присутствует инструкция задания метаданных с помощью выражения @author – информация об авторе проекта для утилиты создания документации javadoc. Метаданные – это некая информация, которая не относится к работе программы и не включается в неё при компиляции, но сопровождает программу и может быть использована другими программами для проверки прав на доступ к ней или её распространения, проверки совместимости с другими программами, указания параметров для запуска класса и т.п. В данном месте исходного кода имя “User” берётся средой разработки из операционной системы по имени папки пользователя. Его следует заменить на имя реального автора, т.е. в нашем случае на “Вадим Монахов”.

Далее следует объявление класса Main, который является главным классом приложения. В нём объявлены две общедоступных (public) подпрограммы. Первой из них является конструктор:

public Main() {

}

Его имя совпадает с именем класса. Он занимается созданием объектов типа Main. Обычно такой конструктор вызывается из метода main, и с его помощью создаётся всего один объект, “олицетворяющий” собой приложение. Но, вообще говоря, таких объектов в простых программах может и не создаваться, как это и происходит в нашем случае.

Все классы и объекты приложения вызываются и управляются из метода main, который объявлен далее и выглядит следующим образом:

public static void main(String[] args) {

}

Он является методом класса, и поэтому для его работы нет необходимости в создании объекта, являющегося экземпляром класса Main. Хотя если этот объект создаётся, это происходит во время работы метода main.

Метод main является главным методом приложения и управляет работой запускаемой программы. Он автоматически вызывается при запуска приложения. Параметром args этого метода является массив строк, имеющий тип String[].Это параметры командной строки, которые передаются в приложение при его запуске. Слово String означает “Строка”, а квадратные скобки используются для обозначения того, что это массив строк.

После окончания выполнения метода main приложение завершает свою работу.

При объявлении любого метода в Java сначала указывается модификатор видимости, указывающий права доступа к методу, затем другие модификаторы, после чего следует тип возвращаемого методом значения. Если модификатор видимости не указан, считается, что это private (читается “прайвит”)– “закрытый, частный”, не позволяющий доступ к методу из других классов.

Конструкторы представляют особый случай, в них имя типа и имя метода совпадают. В Java они не считаются методами, хотя в других языках программирования такого тонкого различия не делается.

Далее следует имя метода, после чего в круглых скобках идёт список параметров (аргументов), передаваемых в данный метод при его вызове. После этого в фигурных скобках идёт тело метода , то есть его реализация – пишется тот алгоритм, который будет выполняться при вызове метода.

В языке Java, как и в C/C++ подпрограммы всегда являются подпрограммами-функциями, возвращающими какое-либо значение. Если надо написать подпрограмму-процедуру, в которой не надо возвращать никакого значения, в C/C++/Java пользуются подпрограммами-функциями с типом возвращаемого значения void – “пустота, пустое пространство”. Как и происходит в случае метода main.

Среда NetBeans создаёт заготовку методов – в них имеется пустое тело. Для осуществления методом какой-либо деятельности следует дописать свой собственный код. Напишем традиционный пример – вывод сообщения “Привет!”. Для этого вместо комментария

// TODO code application logic here

(“описать тут логику работы приложения”) напишем строку вывода текста

System.out.println("Привет!");

Класс System, “система”, имеет поле out, “наружу”. Это объект, предназначенный для поддержки вывода. У него есть метод println, предназначенный для вывода текста в режиме консоли.

Консольный ввод-вывод ранее широко применялся в операционных системах, ориентированных на работу в режиме командной строки. При этом основным средством взаимодействия пользователей с программами служила текстовая консоль ( “пульт управления”). В ней устройством ввода служила клавиатура, а устройством вывода – окно операционной системы, обеспечивающее вывод текста в режиме пишущей машинки (системным шрифтом с буквами, имеющими одинаковую ширину). Очень много примеров программ в учебных курсах по Java ориентированы на работу в таком режиме. В настоящее время в связи с тем, что подавляющее большинство пользователей работают с программами в графическом режиме, работу в консольном режиме нельзя рассматривать как основную форму ввода-вывода. Тем более, что NetBeans позволяет без особых усилий создавать графический пользовательский интерфейс (GUI – Graphics User Interface) приложения. А консольный режим следует применять только как промежуточный, удобный в отладочном режиме как средство вывода вспомогательной информации.

2.6. Компиляция файлов проекта и запуск приложения

В современных средах разработки используется два режима компиляции – compile (“скомпилировать”) и build (“построить”). В режиме “compile” происходит компиляция только тех файлов проекта, которые были изменены в процессе редактирования после последней компиляции. А в режиме “build” перекомпилируются заново все файлы.

Для компиляции проекта следует выбрать в меню среды разработки Build / Build Main Project (или, что то же, клавиша <F 11 >, или на панели инструментов иконка с голубой книжкой и гаечным ключом). При этом будут заново скомпилированы из исходных кодов все классы проекта.

Пункт Build / Clean and Build Main Project (или, что то же, комбинация клавиш <Shift > <F 11 >, или на панели инструментов иконка с оранжевой книжкой и веником) удаляет все выходные файлы проекта (очищает папки build и dist), после чего по новой компилируются все классы проекта.

Пункт Build / Generate Javadoc for JavaApplication 1” запускает создание документации по проекту. При этом из исходных кодов классов проекта выбирается информация, заключённая в документационные комментарии /** … */, и на её основе создаётся гипертекстовый HTML-документ.

Пункт Build / Complile Main . java (или, что то же, клавиша <F 9 >) компилирует выбранный файл проекта – в нашем случае файл Main.java, в котором хранятся исходные коды класса Main.

Для того чтобы запустить скомпилированное приложение из среды разработки, следует выбрать в меню среды разработки Run / Run Main Project (или, что то же, клавиша <F 6 >, или на панели инструментов иконка с зелёным и жёлтыми треугольниками). При запуске приложение всегда автоматически компилируется (но не “строится”), так что после внесения изменений для запуска обычно достаточно нажать <F 6 >.

После запуска нашего проекта в выходной консоли, которая находится в нижней части окна проекта, появится служебная информация о ходе компиляции и запуска:

Информация о ходе компиляции и запуска в выходной консоли.

В неё же осуществляется вывод методов System.out.print и System.out.println.

Метод System.out.print отличается от метода System.out.println только тем, что в println после вывода осуществляется автоматический переход на новую строку, а в print продолжается вывод в ту же строку консоли. Поэтому вывод

System.out.println("Привет!");

System.out.println("Привет!");

Даст текст

Привет!

Привет!

а

System.out.print("Привет!");

System.out.print("Привет!");

даст

Привет!Привет!

2.7. Структура проекта NetBeans

Рассмотрим, из каких частей состоит проект NetBeans. На рисунке показаны основные элементы, отображаемые в среде разработки.

Это Source Packages (пакеты исходного кода), Test Packages (пакеты тестирования), Libraries (библиотеки) и Test Libraries (библиотеки поддержки тестирования). Ветви дерева представления элементов проекта можно разворачивать или сворачивать путём нажатия на узлы, отмеченные плюсами и минусами. Мы пока будем пользоваться только пакетами исходного кода.

В компонентной модели NetBeans пакеты приложения объединяются в единую конструкцию – модуль. Модули NetBeans являются базовой конструкцией не только для создания приложений, но и для написания библиотек. Они представляют собой оболочку над пакетами (а также могут включать в себя другие модули).

В отличии от библиотек Java скомпилированный модуль – это не набор большого количества файлов, а всего один файл, архив JAR (Java Archive, архив Java). В нашем случае он имеет то же имя, что и приложение, и расширение .jar : это файл JavaApplication1.jar. Модули NetBeans гораздо лучше подходят для распространения, поскольку не только обеспечивают целостность комплекта взаимосвязанных файлов, но и хранят их в заархивированном виде в одном файле, что намного ускоряет копирование и уменьшает объём занимаемого места на носителях.

Отметим не очень удобную особенность NetBeans – после сохранения проекта и закрытия среды разработки не сохраняется конфигурация открытых окон и развёрнутых деревьев проекта - деревья проектов показываются в свёрнутом виде. Поэтому для того, чтобы вновь попасть в режим редактирования исходного кода нашего приложения, в окне Projects, “Проекты” (левом верхнем окне среды разработки) следует развернуть последовательность узлов JavaApplication1/Source Packages/javaapplication1/ . Это делается нажатием на плюсики в соответствующих узлах или двойным щелчком по имени узла. Затем надо сделать двойной щелчок с помощью левой кнопкой мыши по имени узла Main.java, либо с помощью щелчка правой кнопкой мыши по этому имени открыть всплывающее меню и выбрать в нём первый пункт – “Open”.

Имеется и более простой способ. По умолчанию сначала открывается окно Welcome (“Привет”, “Приветствие”). Но среда разработки сохраняет список открытых окон, и в верхней части окна редактирования кода щелчком мыши можно выбрать нужное имя окна. Хотя при этом не видна структура проекта, так что первый способ во многих случаях может быть предпочтительным.

Если вы открываете новый проект, старый не закрывается. И в дереве проектов видны все открытые проекты. То же относится и к списку открытых окон. Это позволяет работать сразу с несколькими проектами, например – копировать в текущий проект участки кода из других проектов. Один из открытых проектов является главным (Main Project) – именно он будет запускаться на исполнение по Run / Run Main Project . Для того, чтобы установить какой-либо из открытых проектов в качестве главного, следует в дереве проектов с помощью правой кнопкой мыши щелкнуть по имени проекта и выбрать пункт меню Set Main Project. Аналогично, для того, чтобы закрыть какой-либо из открытых проектов, следует в дереве проектов с помощью правой кнопкой мыши щелкнуть по имени проекта и выбрать пункт меню Close Project.

Рассмотрим теперь структуру папок проекта NetBeans. По умолчанию головная папка проекта располагается в папке пользователя. В операционной системе.

Windows® XP проект по умолчанию располагается в папке C:\Documents and Settings\ИмяПользователя\ . Дальнейшее расположение папок и файлов приведено ниже, при этом имена папок выделены жирным шрифтом, а имена вложенных папок и файлов записаны под именами их головных папок и сдвинуты относительно них вправо.

build

classes

javaapplication1

Main.class

… .class

META-INF

dist

javadoc

lib

JavaApplication1jar

README.TXT

nbproject

src

javaapplication1

Main.java

… .java

… .form

META-INF

test

build.xml

manifest.mf

- В папке build хранятся скомпилированные файлы классов, имеющие расширение .class.

- В папке dist - файлы, предназначенные для распространения как результат компиляции (модуль JAR приложения или библиотеки, а также документация к нему).

- В папке nbproject находится служебная информация по проекту.

- В папке src - исходные коды классов. Кроме того, там же хранится информация об экранных формах (которые будут видны на экране в виде окон с кнопками, текстом и т.п.). Она содержится в XML-файлах, имеющих расширение .form.

- В папке test - сопроводительные тесты, предназначенные для проверки правильности работы классов проекта.

Приведём перевод файла README.TXT, находящегося в папке dist - там же, где архив JAR, предназначенный для распространения как файл приложения:

========================

ОПИСАНИЕ ВЫВОДА КОМПИЛЯЦИИ

========================

Когда Вы компилируете проект приложения Java, которое имеет главный класс, среда разработки (IDE) автоматически копирует все файлы JAR-архивов, указанные в classpath ваших проектов,

в папку dist/lib. Среда разработки также автоматически прибавляет путь к каждому из этих архивов в файл манифеста приложения (MANIFEST.MF).

Чтобы запустить проект в режиме командной строки, зайдите в папку dist и

наберите в режиме командной строки следующий текст:

java -jar "JavaApplication3.jar"

Чтобы распространять этот проект, заархивируйте папку dist (включая папку lib), и распространяйте ZIP-архив.

Замечания:

* Если два JAR-архива, указанные в classpath ваших проектов, имеют одинаковое имя, в папку lib будет скопирован только первый из них.

* Если в classpath указана папка с классами или ресурсами, ни один из

элементов classpath не будет скопирован в папку dist.

* Если в библиотеке, указанной в classpath, также имеется элемент classpath, указанные в нём элементы должны быть указаны в пути classpath времени выполнения проектов.

* Для того чтобы установить главный класс в стандартном проекте Java, щёлкните правой кнопкой мыши в окне Projects и выберите Properties. Затем выберите Run и введите данные

о названии класса в поле Main Class. Кроме того, Вы можете вручную ввести

название класса в элементе Main-Class манифеста.

2.8. Создание в NetBeans приложения Java с графическим интерфейсом

Экранной формой называется область, которая видна на экране в виде окна с различными элементами - кнопками, текстом, выпадающими списками и т.п. А сами эти элементы называются компонентами.

Среды, позволяющие в процессе разработки приложения в интерактивном режиме размещать на формы компоненты и задавать их параметры, называются RAD-средами. RAD расшифровывается как Rapid Application Development - быстрая разработка приложений.

В NetBeans и других современных средах разработки такой процесс основан на объектной модели компонентов, поэтому он называется Объектно-Ориентированным Дизайном (OOD – Object-Oriented Design).

NetBeans является RAD-средой и позволяет быстро и удобно создавать приложения с развитым графическим пользовательским интерфейсом (GUI). Хотя языковые конструкции Java, позволяющие это делать, не очень просты, на начальном этапе работы с экранными формами и их элементами нет необходимости вникать в эти тонкости. Достаточно знать основные принципы работы с такими проектами.

С точки зрения автора изучение того, как создавать приложения с графическим интерфейсом, весьма важно для начинающих программистов, и это следует делать с самых первых шагов по изучению Java.

Во-первых, с самого начала осваивается создание полноценных приложений, которые можно использовать в полезных целях. Трудно месяцами изучать абстрактные концепции, и только став профессионалом иметь возможность сделать что-то такое, что можно показать окружающим. Гораздо интереснее и полезнее сразу начать применять полученные знания на практике.

Во-вторых, такой интерфейс при решении какой-либо задачи позволяет лучше сформулировать, какие параметры надо вводить, какие действия и в какой последовательности выполнять, и что в конце концов получается. И отобразить всё это на экране: вводимым параметрам будут соответствовать пункты ввода текста, действиям – кнопки и пункты меню, результатам – пункты вывода текста.

Пример открытия проекта с существующим исходным кодом.

В NetBeans 5.0 имелся хороший пример GUI-приложения, однако в NetBeans 5.5 он отсутствует. Поэтому для дальнейшей работы следует скопировать аналогичный пример с сайта автора или сайта, на котором выложен данный учебный курс. Пример называется JavaApplicationGUI_example.

Сначала следует распаковать zip-архив, и извлечь находящуюся в нём папку с файлами проекта в папку с вашими проектами (например, C:\Documents and Settings\User). Затем запустить среду NetBeans, если она не была запущена, и закрыть имеющиеся открытые проекты, чтобы они не мешали. После чего выбрать в меню File/Open Project, либо или на панели инструментов иконку с открывающейся фиолетовой папочкой, либо нажать комбинацию клавиш <Shift>+<Ctrl>+O. В открывшемся диалоге выбрать папку JavaApplicationGUI_example (лучше в неё не заходить, а просто установить выделение на эту папку), после чего нажать кнопку Open Project Folder.

При этом, если не снимать галочку “Open as Main Project”, проект автоматически становится главным.

В окне редактора исходного кода появится следующий текст:

/*

* GUI_application.java

*

* Created on 22 Июня 2006 г., 13:41

*/

package java_gui_example;

/**

*

* @author Вадим Монахов

*/

public class GUI_application extends javax.swing.JFrame {

/**

* Creates new form GUI_application

*/

public GUI_application() {

initComponents();

}

/** This method is called from within the constructor to

* initialize the form.

* WARNING: Do NOT modify this code. The content of this method is

* always regenerated by the Form Editor.

*/

+Generated Code

private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt)

{

System.exit(0);

}

/**

* @param args the command line arguments

*/

public static void main(String[] args) {

java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {

new GUI_application().setVisible(true);

}

});

}

// Variables declaration - do not modify

private javax.swing.JMenuItem aboutMenuItem;

private javax.swing.JMenuItem contentsMenuItem;

private javax.swing.JMenuItem copyMenuItem;

private javax.swing.JMenuItem cutMenuItem;

private javax.swing.JMenuItem deleteMenuItem;

private javax.swing.JMenu editMenu;

private javax.swing.JMenuItem exitMenuItem;

private javax.swing.JMenu fileMenu;

private javax.swing.JMenu helpMenu;

private javax.swing.JMenuBar menuBar;

private javax.swing.JMenuItem openMenuItem;

private javax.swing.JMenuItem pasteMenuItem;

private javax.swing.JMenuItem saveAsMenuItem;

private javax.swing.JMenuItem saveMenuItem;

// End of variables declaration

}

Поясним некоторые его части. Указание пакета java_gui_example, в котором будет располагаться код класса приложения, нам уже знакомо. Декларация самого класса GUI_application в данном случае несколько сложнее, чем раньше:

public class GUI_application extends javax.swing.JFrame

Она означает, что задаётся общедоступный класс GUI_application, который является наследником класса JFrame, заданного в пакете swing, вложенном в пакет javax. Слово extends переводится как “расширяет” (класс-наследник всегда расширяет возможности класса-прародителя).

Общедоступный конструктор GUI_application()создаёт объект приложения и инициализирует все его компоненты, методом initComponents(), автоматически генерируемом средой разработки и скрываемом в исходном коде узлом +Generated Code.

Развернув узел, можно увидеть реализацию этого метода, но изменить код нельзя. Мы не будем останавливаться на том, что в нём делается.

Далее следует закрытый (private) метод