Java — Вопрос по конструкциям языка Java


Содержание

Изучаем Java

Вы здесь: Главная >> Java-самоучитель >> Конструкции выбора в языке Java

Обучающие курсы:

Конструкции выбора в языке Java

Конструкции выбора

Конструкции выбора позволяют передавать выполнение программы разным блокам кода в зависимости от условия (если оно равно значению true, то данный блок выполняется, false — нет).

В языке Java имеются две конструкции выбора —switch и if. else.

Первая конструкция выбора, которую мы рассмотрим,— switch. Она позволяет выполнять какие-либо действия в зависимости от значения переменной.

Схема конструкции switch имеет следующий вид.

В этой конструкции необходимо задать имя переменной, а после ключевого слова case указать ее возможное значение. Если переменная содержит это значение, то выполняются операторы, которые следуют после ключевого слова case с данным значением. Если же значение переменной в блоках case не равно ни одному из предложенных значений, то выполняются операторы после ключевого слова default.

В листинге 3.6 приведен пример использования конструкции switch.

Листинг 3.6.
Пример использования конструкции switch

Чтобы выйти из конструкции выбора, не выполняя все оставшиеся операторы от данного ключевого слова case до конца блока, следует использовать инструкцию break.

Если в конструкции case из листинга 3.6 убрать все операторы break, то, когда значение переменной i будет равно 1, будут выполняться абсолютно все операторы в блоке switch.

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

Есть еще конструкция if . else. Схема двух возможных форм данной конструкции выбора следующая.

if <условие!) // Если условие1 = true, то:
операторы
else if (условие2) // Если условие2 = true, то:
операторы

else if (условиеN) // Если yonoBneN = true, то:
операторы
else // Если все условия = false, то:
операторы

В листингах 3.7 и 3.8 приведен пример использования первой и второй формы соответственно.

Листинг 3.7.
Пример использования первой формы конструкции if. else

Листинг 3.8.
Пример использования второй формы конструкции if. else

Можно вкладывать конструкции if одна в другую. В листинге 3.9 представлен пример подобной программы.

Листинг 3.9.
Пример использования вложенных конструкций if

Фактически вторую форму можно рассматривать как вложенные конструкции if. е1sе изначально рассмотренного типа.

Сергей Владимирцев
11.02.2011

Конструкции языка Java

28.05.2011, 20:44

О Java. Выбор языка
Здравствуйте. Такая ситуация. Долгое время выбирал язык программирования для решения своих задач.

Понимание языка java
Только-только начал приглядываться к java. Есть опыт только в с++. Возник такой вопрос. В с++ можно.

Поддержка русского языка в Java.
Разработчики не включили в спецификацию Явы поддержку русского языка: .

Актуальность java языка сегодня?
Добрый день. Недавно я начал изучение языка java и, пока мне все очень понятно и нравится. Но.

План по изучению языка Java
Добрый день, форумчане! Изучаю язык программирования Java пока по книге Shildt G – Java 8.

Java — Вопрос по конструкциям языка Java

Для того, чтобы изменить последовательность выполнения фрагментов программы, в языке Java применяются конструкции if , if-else и switch.

В этом уроке мы рассмотрим:

В конце урока предложены упражнения для закрепления материала.

Конструкция if-else имеет следующий вид:

Блок else не является обязательным.

Логическое выражение это выражение (или переменная), возвращающее значение типа boolean .

Логические операторы в Java.

В логическом выражении могут использоваться следующие логические операторы: ==, !=, =,>, Отличие == и equals

Оператор == работает иначе на объектных типах данных, нежели на примитивных. Когда мы используем объекты и хотим проверить их равенство, то оператор == укажет нам лишь на то, являются ли объекты одними и теми же или нет. Если же необходимо проверить логическое равенство объектов, то следует использовать метод equals . Пример:

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

Ели логическое выражение в скобках правдиво, то выполняется , блок кода в фигурных скобках <> после if. Если логическое выражение принимает значение false, то ничего не происходит.

Условный оператор if-else

Конструкция if-else отличается от предыдущей тем, что если логическое выражение в круглых скобках принимает значение false, то выполняется блок кода, находящийся в фигурных скобках после ключевого слова else

Возможные сокращения if-else

1. Если блоки кода if, else содержат лишь одну строку, то можно обойтись без использования фигурных скобок. Предыдущий пример можем записать так:

2. Существует еще один способ сокращения оператора if-else при помощи оператора ? : . Запишем предыдущий пример следующим образом:

Общая форма записи условия выглядит следующим образом:

Если Логическое_выражение принимает значение true, то выполняется Выражение1, а иначе — Выражение2. Внимание: при использовании этой конструкции два последних выражения должны иметь один и тот же тип.

Условный оператор switch — case

Условный оператор switch — case удобен в тех случаях, когда количество вариантов очень много и писать для каждого if-else очень долго. Конструкция имеет следующий вид :

switch работает с такими примитивными типами данных как: byte , short , char , и int . Также с типами Enum, классом String и несколькими специальными классами-оболочками примитивных типов: Character, Byte, Short, Integer.

Выражение в круглых скобках после switch сравнивается со значениями, указанными после слова case, и, в случае совпадения, управление передается соответствующему блоку кода. Если выражение не совпадает ни с одним вариантом case, то управление передается блоку default, который не является обязательным. После выполнения соответствующего блока, оператор break вызывает завершение выполнения оператора switch. Если break отсутствует, то управление передается следующему блоку за только что выполненным.

В следующем примере, для целочисленного значения, представляющего день недели, определяется его название в виде строки. Для значения 3, переменная dayString примет значение «Среда».

4. Java — Синтаксис языка для начинающих

Когда мы рассматриваем java-программу, она может быть определена как совокупность объектов, которые взаимодействуют с помощью вызова методов друг друга. Теперь позвольте нам кратко разобраться в синтаксисе языка Java, что же класс, объект, методы и переменные экземпляра означают.

Объект — объекты имеют состояние и поведение. Например: собака может иметь состояние — цвет, имя, а также и поведение — кивать, бежать, лаять, кушать. Объект является экземпляром класса.

Класс — может быть определен как шаблон, который описывает поведение объекта.

Метод — является в основном поведением. Класс может содержать несколько методов. Именно в методах логически записанные данные манипулируют и выполняют все действия.

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

Содержание

Первая программа и знакомство с синтаксисом языка

Давайте рассмотрим простой код, в результате которого будут выведены на экран слова «Привет мир!», а за одно и синтаксис Java.

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

  • Откройте блокнот и добавьте код, указанный выше.
  • Сохраните файл как «MyFirstJavaProgram.java». Ниже мы рассмотрим синтаксис Java и узнаем почему именно под таким именем.
  • Откройте окно командной строки и перейдите в каталог, где был сохранен файл. Предположим, что это «C:\».
  • Введите «Javac MyFirstJavaProgram.java» и нажмите ввод, чтобы скомпилировать код. Если нет ошибки в коде, командная строка приведет Вас к следующей строке: (Assumption: The path variable is set).
  • Теперь введите «java MyFirstJavaProgram» для запуска программы.
  • Теперь Вы увидите «Привет Мир!», напечатанный в окне.

Основы синтаксиса языка Java

Очень важно знать и помнить следующие моменты в синтаксисе:

  • Чувствительность к регистру — Java чувствителен к регистру, то есть идентификатор Hello и hello имеют разный смысл.
  • Название классов — для всех первая буква должна быть в верхнем регистре.
  • Если несколько слов используются, чтобы сформировать название класса, первая буква каждого внутреннего слова должна быть в верхнем регистре, например, «MyJavaClass».
  • Название методов — в синтаксисе Java все имена методов должны начинаться с буквы нижнего регистра.
  • Если несколько слов используются, чтобы сформировать имя метода, то первая буква каждого внутреннего слова должна быть в верхнем регистре, например, «public void myMethodName()».
  • Название файла программы — наименование файла программы должно точно совпадать с именем класса.
  • При сохранении файла, Вы должны сохранить его, используя имя класса (помните о чувствительности к регистру) и добавить «.java» в конце имени (если имена не совпадают, Ваша программа не будет компилироваться), например, «MyJavaProgram» — это название класса, тогда файл должен быть сохранен как «MyJavaProgram.java».
  • public static void main(String args[]) — обработка программы начинается с метода main(), который является обязательной частью каждой программы.

Идентификаторы в Java

Идентификаторы — имена, используемые для классов, переменных и методов. Все компоненты Java требуют имена.

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

  • Каждый идентификатор должен начинаться с «A» до «Z» или «a» до «z», «$» или «_».
  • После первого символа может иметь любую комбинацию символов.
  • Ключевое слово не может быть использовано в качестве идентификатора.
  • Самое главное — идентификатор в Java чувствителен к регистру.
  • Пример правильного написания: age, $salary, _value, __1_value.
  • Пример неправильного написания: 123abc, -salary.

Перечисления

Перечисления были введены в Java 5.0. Они ограничивают переменную, чтобы выбрать только одно из нескольких предопределенных значений. Значения в этом перечисляемом списке называются перечисления.

С использованием перечисления в Java можно уменьшить количество ошибок в коде.

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

Пример кода перечисления в Java

Полученный результат выше приведенного примера:

Примечание: в Java перечисления могут быть объявлены как самостоятельно, так и внутри класса. Методы, переменные, конструкторы могут быть определены также внутри перечисления.

Типы переменных

Далее в Java мы увидим следующие существующие типы:

  • Локальные переменные.
  • Переменные класса (статические).
  • Переменные экземпляра (динамические).

Модификаторы

Как и в других языках, в Java можно модифицировать классы, методы и так далее, с помощью модификаторов. Модификаторы в Java делится на две категории:

  • С доступом: default, public, protected, private.
  • Без доступа: final, abstract, strictfp.

Более подробно рассмотрим модификаторы класса, модификаторы методов и другие в следующем разделе.

Массив

В Java массив является объектом, который хранит несколько переменных одного и того же типа. Тем не менее, сам массив является объектом. Мы рассмотрим, как создать и заполнить массив в последующих главах.

Комментарии в Java

Язык Java поддерживает однострочные и многострочные комментарии, они очень похожи на используемые в С и С++. Все символы недоступны внутри любых комментариев и игнорируются компилятором.

Пример комментария

Ключевые слова в Java

Всего зарезервировано 50 ключевых слов в Java. Ниже в таблице приведен список зарезервированных ключевых слов.

Список ключевых слов
abstract assert boolean break
byte case catch char
class const continue default
do double else enum
extends final finally float
for goto if implements
import instanceof int interface
long native new package
private protected public return
short static strictfp super
switch synchronized this throw
throws transient try void
volatile while

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

Пустая строка

Пустая строка — строки в Java, содержащие только пробелы, возможно с комментарием. Java полностью игнорирует строку имеющую пробелы и комментарии.

Наследование

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

Интерфейс

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

Интерфейс определяет методы, полученного класса (подкласса), и как их следует использовать. Однако осуществление методов полностью зависит от подкласса.

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

Уроки по основам языка программирования JAVA для начинающих

Уроки по основам языка java

Основы java для начинающих

Курс JAVA для начинающих рассчитан на новичков в программировании. Наши уроки по java с самого начала дадут вам представление о языке программирования java, его основных принципах и возможностях. После прохождения основ Java вы сможете уверенно осваивать уроки по разработке мобильных приложений на андроид. Уроки обновляются и дополняются. Желаем удачи на пути программиста!

Список уроков по Java

Справочник по языку программирования JAVA

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

Справочник по языку программирования java. Материал взят из открытых источников.

Уроки по андроид-программированию:

Продвинутые курсы разработки приложений для андроид:

Продвинутые курсы по созданию приложений и игр для андроид помогут вам за очень короткий срок создать реальное работающее android-приложение или игру, внедрить в него рекламные баннеры и загрузить в маркет Google Play.

Введение в программирование на языке Java

Оглавление


О данном руководстве

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

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

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

В данном руководстве будет рассмотрена установка Java-платформы на вашей машине, установка и использование Eclipse, свободно распространяемой интегрированной среды разработки (integrated development environment — IDE), для написания Java-кода. Вы изучите основы программирования на языке Java (в том числе ООП-парадигму и ее применение в Java), синтаксис и использование Java, создание объектов и добавление поведения, работу с коллекциями и обработку ошибок, советы по улучшению кода. К концу руководства вы станете Java-программистом — начинающим, но, тем не мене, Java-программистом.

Для выполнения примеров из данного руководства необходимо наличие установленных Java 2 Platform Standard Edition (J2SE) версии 1.4.2 или выше и Eclipse IDE. Не беспокойтесь, если вы еще не установили эти пакеты — мы покажем вам, как это сделать в разделе «Начало работы». Все примеры кода из данного руководства были протестированы с J2SE 1.4.2 на Windows XP. Однако одной из великолепных возможностей платформы Eclipse является то, что она работает практически на всех операционных системах, которые вы можете использовать, в том числе Windows 98/ME/2000/XP, Linux, Solaris, AIX, HP-UX и даже Mac OS X.

Начало работы

В следующих нескольких разделах я в пошаговом режиме рассмотрю процедуру загрузки и установки Java 2 Platform Standard Edition (J2SE) версии 1.4.2 и Eclipse IDE. Первая система дает вам возможность компилировать и выполнять Java-программы. Вторая предоставляет мощную и дружественную среду для написания кода на языке программирования Java. Если Java SDK и Eclipse у вас уже установлены, можете сразу перейти к разделу «Краткая экскурсия по Eclipse» или к разделу «Концепции ООП».

Первоначальной целью языка Java являлось предоставление возможности для программистов писать одну программу, которая могла бы работать на любой платформе. Эту цель можно выразить афоризмом «Write Once, Run Anywhere» (написать один раз, выполнять везде) (WORA). В действительности все не так просто, но все идет именно к этому. Поддерживают эту цель различные компоненты технологии Java. Платформа Java поставляется в трех редакциях: Standard, Enterprise и Mobile (последние две предназначены для разработки мобильных устройств). Мы буди работать с J2SE, в которую входят все основные библиотеки Java. Все что вам нужно — загрузить и установить ее.

Чтобы загрузить J2SE SDK (software development kit — комплект для разработки программного обеспечения), выполните следующие действия:

  1. Откройте браузер и перейдите на страницу Java Technology. В верхней средней части страницы вы увидите ссылки на различные предметные области Java-технологии. Выберите J2SE (Core/Desktop).
  2. В списке текущих версий J2SE выберите J2SE 1.4.2 .
  3. В левой навигационной панели появившейся страницы выберите Downloads .
  4. На данной странице имеется несколько загружаемых пакетов. Найдите и выберите ссылку Download J2SE SDK .
  5. Подтвердите условия лицензии и нажмите Continue .
  6. Вы увидите список загружаемых пакетов для различных платформ. Выберите соответствующий пакет для вашей системы.
  7. Сохраните файл на ваш жесткий диск.
  8. После завершения загрузки запустите программу установки SDK на ваш жесткий диск, желательно в какую-либо папку с удобным названием в корне диска.

Все! Теперь у вас есть Java-среда. Следующий шаг — установка интегрированной среды разработки (integrated development environment — IDE).

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

Теперь не надо платить за отличную IDE. Eclipse IDE является проектом с открытым исходным кодом, который вы можете бесплатно загрузить и использовать. Eclipse хранит и отслеживает ваш Java-код в файлах, расположенных в вашей файловой системе. Вы можете также использовать Eclipse для работы с кодом, расположенным в CVS-репозитории. Хорошей новостью является то, что Eclipse позволяет вам работать с нужными файлами, но скрывает детали файлов при работе с различными Java-конструкциями, такими как классы (которые мы рассмотрим подробно далее).

Загрузить и установить Eclipse просто. Выполните следующие действия:

  1. Откройте браузер и перейдите на Web-сайт Eclipse.
  2. Нажмите ссылку Downloads в левой части страницы.
  3. Нажмите ссылку Main Eclipse Download Site для перехода на страницу загрузки проекта Eclipse.
  4. Вы увидите список типов и названий версий компоновки. Нажмите ссылку 3.0 .
  5. В средней части страницы вы увидите список Eclipse SDK для различных платформ; выберите соответствующую вашей платформе версию.
  6. Сохраните файл на ваш жесткий диск.
  7. После завершения загрузки запустите программу установки и установите Eclipse на вашем жестком диске, желательно в каталоге с удобным названием в корне диска.

Все, что осталось — это настроить IDE.

Для использования Eclipse при написании Java-кода вы должны указать Eclipse, где на вашей машине расположена платформа Java. Выполните следующие действия:

  1. Запустите Eclipse, выполнив двойной щелчок мышкой на файле eclipse.exe или на эквивалентном файле для вашей платформы.
  2. Когда появится экран Welcome, нажмите ссылку Go To The Workbench . Это приведет вас в так называемую перспективу Resource (более подробно об этом далее).
  3. Выберите Window>Preferences>Installed JREs , что позволит вам указать месторасположение вашей Java-среды, установленной в системе (см. рисунок 1).

Рис. 1. Настройки Eclipse

  • Eclipse найдет установленные Java Runtime Environment (JRE), но вы должны явно указать одну из них, установленную в разделе «Установка Java SDK». Это можно сделать в диалоговом окне Preferences. Если Eclipse выводит существующую JRE, выберите ее и нажмите Edit ; в противном случае нажмите Add .
  • Укажите путь к папке JRE JDK, который вы установили в разделе «Установка Java SDK».
  • Нажмите OK .
  • Теперь Eclipse настроен на компилирование и запуск Java-кода. В следующем разделе мы совершим краткую экскурсию по среде Eclipse, для того чтобы вы познакомились с этой программой.

    Работа с Eclipse — это обширная тема, и она, в основном, выходит за рамки данной статьи. Здесь же мы рассмотрим только самое необходимое для знакомства с работой среды Eclipse и ее использованием для Java-разработки.

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

    Вообще говоря, Eclipse имеет перспективы, содержащие виды (view). В перспективе Resource вы увидите вид Navigator, вид Outline и др. Вы можете по желанию перемещать эти виды в любую позицию на экране. Eclipse — это неограниченно настраиваемая среда, хотя пока для работы нам достаточно размещения по умолчанию. Но то, что мы видим, не позволяет нам сделать то, что мы хотим. Первым шагом для написания Java-кода в Eclipse является создание Java-проекта. Это не конструкция языка Java; это просто конструкция Eclipse, которая дает возможность организовать ваш Java-код. Для создания Java-проекта выполните следующие действия:


      Выберите File>New>Project для отображения мастера New Project (рисунок 2). Это на самом деле «мастер мастеров»; другими словами, — это мастер, позволяющий вам выбрать мастера для использования (мастер New Project, мастер New File и т.д.).

    Рис. 2. Мастер New project

  • Выберите Java Project и нажмите Next .
  • Введите какое-либо название проекта (например, «Intro»), оставьте выбранными все настройки по умолчанию и нажмите Finish .
  • Сейчас Eclipse должен спросить вас, желаете ли вы переключиться в перспективу Java. Нажмите No .
  • Вы только что создали Java-проект с названием Intro, который вы должны увидеть в виде Navigator в верхнем левом углу экрана. Мы не переключились в перспективу Java после создания проекта потому, что существует более подходящая перспектива для наших текущих целей. Нажмите кнопку Open Perspective в панели в верхнем правом углу окна, затем выберите перспективу Java Browsing. Эта перспектива показывает все, что необходимо для легкого создания Java-программ. При создании Java-кода мы рассмотрим дополнительные функциональные возможности Eclipse для создания, изменения и управления вашим кодом. Но перед этим необходимо рассмотреть некоторые основные концепции объектно-ориентированного программирования, что мы и сделаем в следующем разделе. А сейчас завершим этот раздел рассмотрением интерактивной документации по Java.

    Интерфейс прикладного программирования (application programming interface — API) Java очень объемен, поэтому важно уметь находить нужную информацию. Платформа Java достаточно большая и предоставляет вам практически любое инструментальное средство, в котором вы нуждаетесь как программист. Изучение способов использования этих возможностей может потребовать стольких же усилий, что и изучение механизмов языка программирования.

    Если вы перейдете на страницу документации по Java фирмы Sun (ссылка приведена в разделе «Ресурсы»), то увидите ссылку на документацию по API для каждой версии SDK. Выберите версию 1.4.2 для просмотра документации.

    Вы увидите в вашем браузере три фрейма:

    • Список встроенных пакетов в левом верхнем фрейме
    • Список всех классов в нижнем левом фрейме
    • Подробная информация по выбранной теме в правом фрейме

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

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

    Java — это так называемый объектно-ориентированный (ОО) язык, при помощи которого вы можете заниматься объектно-ориентированным программированием (ООП). Такой стиль программирования очень отличается от процедурного программирования и может показаться немного странным для большинства программистов, не сталкивавшихся с ООП. Прежде всего, надо понять, что такое объект; именно на этом понятии базируется ООП.

    Объект — это самостоятельный фрагмент кода, который знает о себе и может рассказать об этом другим объектам, если они зададут вопрос, который он понимает. Объект имеет члены (переменные) и методы, являющиеся вопросами, на которые он может ответить (даже если они не выглядят вопросами). Набор методов, на которые объект знает как реагировать, является его интерфейсом. Некоторые методы являются общедоступными (public), это означает, что другой объект может вызвать (или активизировать) их. Этот набор методов известен под названием public-интерфейс .

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

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

    Обычно концепция объекта остается неизменной и в языке Java и в других объектно-ориентированных языках программирования, хотя реализуют они ее по-разному. Эта концепция универсальна. По этой причине объектно-ориентированные программисты, независимо от применяемого ими языка, общаются не так, как процедурные программисты. Процедурные программисты часто говорят о функциях и модулях. Объектно-ориентированные программисты говорят об объектах и часто говорят о них, используя личные местоимения. Вы часто можете услышать, как один ОО-программист говорит другому: «Этот объект Supervisor говорит здесь объекту Employee «Дай мне свой ID», поскольку он должен назначить задания для Employee».

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

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

    Вы можете запомнить три фундаментальных принципа ООП при помощи акронима PIE (ПНИ):

    • P olymorphism (Полиморфизм)
    • I nheritance (Наследование)
    • E ncapsulation (Инкапсуляция)

    Это все необычные названия, но эти концепции не трудно понять. В следующих нескольких разделах мы подробно рассмотрим каждую из них в обратном порядке.

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

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

    При вашем рождении, говоря с биологической точки зрения, вы являлись комбинацией ДНК ваших родителей. Вы не были точной копией ни одного из них, но были похожи на обоих. ОО использует для объектов этот же принцип. Представьте опять объект Человек. Вспомните, что каждый этот объект имеет национальность. Не все эти объекты имеют одинаковую национальность, но не являются ли они похожими? Конечно! Это не Лошади, или Шимпанзе, или Киты. Это объект Человек. Все объекты Человек имеют определенные общие признаки, отличающие их от животных других типов. Но они немного отличаются друг от друга. Похож ли Ребенок на Подростка? Нет. Они двигаются и говорят по-разному. Но Ребенок определенно является Человеком.

    В терминах ООП Человек и Ребенок являются классами в одной иерархии и (вероятнее всего) Ребенок наследует характеристики и поведение от своего родителя. Мы говорим, что конкретный Ребенок имеет тип Человек, или что этот Ребенок наследуется из объекта Человек. Это не срабатывает в обратную сторону — Человек не обязательно Ребенок. Каждый объект Ребенок является экземпляром класса Ребенок, и когда мы создаем объект Ребенок, мы создаем его экземпляр. Представляйте класс как шаблон для экземпляров этого класса. Обычно то, что может делать объект, зависит от типа объекта или, другими словами, от того, экземпляром какого класса он является. И Ребенок, и Подросток имеют тип Человек, но один может работать, а другой нет.

    В терминах Java Человек — это суперкласс классов Ребенок и Подросток, которые являются подклассами класса Человек. Еще одной концепцией, связанной с наследованием, является абстракция. Человек находится на более высоком уровне абстракции, чем Ребенок или Подросток. Оба они имеют тип Человек, но несколько отличаются. Все объекты Человек имеют некоторые общие свойства (например, имя и возраст). Вы можете создать экземпляр класса Человек? Нет. Вы имеете либо экземпляр класса Ребенок, либо класса Подросток. Человек, в терминах Java, является абстрактным классом. Вы не можете иметь прямой экземпляр класса Человек. Только Ребенок или Подросток, которые оба имеют тип Человек, являются реальными. Рассмотрение абстрактных классов выходит за рамки данного руководства, поэтому мы больше о них говорить не будем.

    Теперь, подумайте, что значит для объекта Ребенок действие «говорить». Мы рассмотрим смысл этого в следующем разделе.

    «Говорит» ли Ребенок также как Подросток? Конечно же, нет. Ребенок издает шум, который не всегда является распознаваемыми словами, которые используют объекты Подросток. Поэтому, когда я создаю экземпляр объекта Ребенок (высказывание «создать экземпляр Ребенка» означает то же самое — слово «объект» подразумевается) и указываю ему «говорить», он может ворковать или булькать. Ожидается, что Подросток будет более внятен.

    В иерархии человечества мы имеем класс Человек на вершине иерархии и классы Ребенок и Подросток ниже, в качестве подклассов. Все объекты Человек могут говорить, поэтому объекты Ребенок и Подросток тоже могут, но делают это по-разному. Ребенок булькает и издает простейшие звуки. Подросток произносит слова. Вот что означает полиморфизм: объекты делают вещи по-разному.

    Как мы увидим, язык Java позволяет создавать первоклассные объекты, но не все в языке является объектом. Это немного не так, как в некоторых других объектных языках, например Smalltalk. Smalltalk является чистым объектно-ориентированным языком, т.е. все в нем является объектом. Язык Java является смесью объектов и других сущностей, не являющихся объектами. Он также позволяет одному объекту знать внутренности другого, если вы, как программист, реализуете такую возможность. Это нарушает принцип инкапсуляции.

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

    Хотя многие ярые сторонники объектно-ориентированного подхода справедливо спорят о том, является ли язык Java объектно-ориентированным или нет, это на самом деле не так уж и важно. Платформа Java появилась, чтобы остаться. Научитесь применять ООП с Java там, где это возможно, и оставьте аргументы о чистоте другим. Язык Java позволит вам писать понятные, относительно лаконичные и управляемые программы, которые достаточно хороши для большинства профессиональных ситуаций.

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

    С точки зрения файловой системы при написании кода вы создаете файл с расширением .java. После компилирования этого файла компилятор Java создает файл с расширением .class, который содержит байт-коды. JVM читает и интерпретирует этот файл во время исполнения, и то, как она делает это, зависит от платформы, на которой вы работаете. Для работы на других платформах вы должны откомпилировать ваш исходный код с библиотеками, специфичными для этой платформы. Как вы понимаете, обещание «Write Once, Run Anywhere» (написать один раз, запускать везде) превращается в высказывание «Write Once, Test Anywhere» (написать один раз, проверить везде). Существуют тонкие (или не такие тонкие) отличия платформ, которые могут вызвать различное выполнение вашего кода на различных платформах.

    При создании Java-объектов JRE автоматически выделяет оперативную память для этого объекта из кучи, которая представляет собой большой пул памяти, доступный на вашей машине. Система времени исполнения отслеживает эти объекты за вас. Когда ваша программа больше не использует их, JRE избавляется от них. Вам не нужно об этом беспокоиться.

    Если вы писали какие-либо программы на языке программирования C++, который тоже является (вероятно) объектно-ориентированным, то знаете, что как программист вы должны распределять и освобождать память для ваших объектов явно при помощи функций malloc() и free() . Для программистов это обременительная задача. Она также и опасна, поскольку может привести к утечкам памяти в ваших программах. Утечка памяти — это ничто иное, как ваша программа, поглощающая оперативную память с угрожающей скоростью, что нагружает процессор машины, на которой работает ваша программа. Java-платформа освобождает вас от каких-либо беспокойств по этому поводу, поскольку она имеет так называемый сборщик мусора .

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

    Как мы уже отмечали ранее, Java-платформа поставляется с инструментами командной строки, которые позволяют компилировать ( javac ) и запускать ( java ) Java-программы. Так зачем же тогда использовать такую IDE как Eclipse? Причина этого заключается в том, что использование инструментов командной строки может стать головной болью для работы с программами любой сложности. Они имеются под рукой, когда необходимы, но использование IDE в большинстве ситуаций является более мудрым решением.

    Главной причиной использования IDE является управление файлами и путями в самой IDE и наличие мастеров, помогающих вам при необходимости изменить вашу среды времени исполнения. Если я хочу откомпилировать Java-программу при помощи инструмента командной строки javac , то должен заранее побеспокоиться об установке переменной среды CLASSPATH , для того чтобы JRE смог найти мои классы, либо я должен установить эту переменную во время компилирования. В такой IDE как Eclipse все, что я должен сделать — это указать Eclipse, где найти мою JRE. Если мой код использует классы, которые я не написал, все что я должен сделать — это указать Eclipse библиотеки, на которые ссылается мой код, и их месторасположение. Это намного проще, чем использование командной строки для ввода ужасно длинных строк, указывающих classpath.

    Если вы хотите или вынуждены использовать инструменты командной строки, то можете найти дополнительную информацию по их использованию на Web-сайте Sun по Java-технологии.

    ООП с использованием Java-технологии

    Java-технология охватывает большую область, но язык сам по себе не является очень большим. Однако описать его — не простая задача. Данный раздел руководства не рассматривает язык полностью. Вместо этого будет рассмотрено все, что вам необходимо знать для начала работы с языком, и то, с чем вы наиболее вероятно столкнетесь как начинающий программист. В других учебниках рассмотрены различные аспекты языка Java, дополнительные полезные библиотеки фирмы Sun (и других источников) и даже разные IDE.

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

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

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

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

    Объявление package идет первым при определении класса:

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

    Например, в пакете java.util.ArrayList java — это узел, util — узел и ArrayList — тоже узел. Последний узел ссылается на файл ArrayList.java .

    В определении класса далее следуют выражения import :

    Когда ваш объект использует объекты из других пакетов, Java-компилятор должен знать, где их найти. Выражения import указывают компилятору месторасположение используемых вами классов. Например, если бы я хотел использовать класс ArrayList из пакета java.util , то должен был бы написать следующее выражение:

    Каждое выражение import заканчивается точкой с запятой, как и большинство выражений в языке Java. Вы можете иметь сколько угодно выражений import для указания Java месторасположения используемых вами классов. Например, если бы я хотел использовать класс ArrayList из пакета java.util и класс BigInteger из пакета java.math , то мог бы написать следующие выражения:

    Если вы импортируете более одного класса из одного и того же пакета, то можете использовать сокращенную запись. Например, если бы я хотел использовать ArrayList и HashMap , оба из пакета java.util , я мог бы импортировать их следующим образом:

    Вы должны указывать выражение import для каждого уникального пакета, из которого вы выполняете импорт.

    Далее идет определение класса :

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

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

    Классы имеют два типа членов: переменные (или данные-члены ) и методы. Все члены класса определены в теле класса, которое находится внутри одного набора фигурных скобок для класса.

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

    • public (открытый): Любой объект любого пакета может видеть переменную.
    • protected (защищенный): Любой экземпляр класса, любой подкласс в этом же пакете и любой не подкласс этого же пакета может видеть переменную. Подклассы в других пакетах не могут видеть переменную.
    • private (закрытый): Ни один объект за исключением конкретного экземпляра данного класса не может видеть переменную, даже подкласс.
    • Спецификатор отсутствует (или p ackage protected ): Только классы того же пакета, в котором находится класс, содержащий переменную, могут видеть ее.

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

    Методы класса определяют, что он может делать. Есть два типа методов в языке Java:

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

    Конструкторы позволяют вам указать, как создавать экземпляр класса. Конструктор объявляется следующим образом:

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

    При вызове конструктора используется ключевое слово new . Конструкторы могут иметь или не иметь параметры (конструктор по умолчанию не имеет). В строгом смысле конструкторы не являются методами или членами класса. Это особенный зверь в языке Java. На практике они чаще всего выглядят и работают как методы, и многие смешивают их вместе. Просто помните, что они особенные.

    Остальными методами в языке Java вы будете пользоваться чаще всего. Объявляются они следующим образом:

    Каждый метод имеет тип возвращаемых данных, но не каждый метод возвращает что-либо. Если метод ничего не возвращает, в качестве возвращаемого типа используется ключевое слово void . Вы можете назвать метод как хотите, если это название является корректным идентификатором (например, он не может начинаться с точки ( . )), но по соглашению имена методов:

    • Используют буквы
    • Начинаются с маленькой буквы
    • Последовательные слова начинаются с больших букв

    Методы вызываются следующим образом:

    Здесь, мы вызываем methodName() объекта instanceOfSomeClass и передаем несколько аргументов. Различия между параметрами и аргументами не велики, но они есть. Метод принимает параметры. Когда вы передаете конкретные значения в вызываемый метод, эти значения являются аргументами вызова.

    Ваш первый Java-объект

    Перейдите в перспективу Java Browsing в Eclipse, если уже не находитесь в ней. Мы собираемся создать первый Java-класс. Первым шагом является создание места, где будет размещаться класс.

    Вместо использования пакета по умолчанию давайте создадим один конкретно для проекта Intro. Выберите File>New>Package . При этом должен отобразиться мастер Package (см. рисунок 3).

    Рис. 3. Мастер Package

    Введите intro.core в качестве имени пакета и нажмите Finish . В рабочей области вы должны увидеть следующий пакет в виде Packages:

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

    Вы можете создать Java-класс в Eclipse, выбрав File>New , но мы вместо этого будем использовать панель инструментов. Посмотрите на верхнюю часть вида Packages и найдите инструменты для создания проектов, пакетов и классов. Нажмите кнопку New Java Class (зеленая буква «C») для отображения мастера New Java Class. Введите Adult в качестве имени класса и примите все значения по умолчанию, нажав Finish . Теперь вы должны увидеть несколько изменений:


      Класс Adult появляется в виде >

    Рис. 4. Рабочая область

  • Пиктограмма пакета intro.core больше не затемнена.
  • Ниже этих видов отображается редактор для Adult.java .
  • Сейчас класс выглядит следующим образом:

    Eclipse генерирует оболочку или шаблон для класса за вас и вставляет оператор package сверху. Пока тело класса пустое. Мы просто должны добавить в него чего-нибудь. Вы можете настроить шаблоны для новых классов, методов и т.д. в мастере Preferences, который использовали ранее ( Window>Preferences ). Можно настроить шаблоны кода в Java>Code Style>Code Templates . Фактически для упрощения отображения кода я собираюсь удалить все комментарии из шаблонов, то есть, все следующие строки: начинающиеся с // комментарии , окруженные символами /* комментарии */ , окруженные символами /** комментарии */ . С этого момента вы не увидите каких-либо комментариев в коде до тех пор, пока мы специально не обсудим их применение, что будет сделано в следующем разделе.

    Однако прежде чем продолжить, давайте продемонстрируем способ работы в Eclipse IDE, который облегчает жизнь. В редакторе измените слово class на clas и подождите несколько секунд. Обратите внимание на то, что Eclipse подчеркнет его красной волнистой линией. Если вы поместите над ней указатель мыши, Eclipse отобразит информационное окно, предупреждающее вас о наличии синтаксической ошибки. Eclipse помогает вам, периодически компилируя ваш код и ненавязчиво предупреждая вас о наличии проблемы. Если бы вы использовали программу командной строки javac , то должны были бы сначала откомпилировать код и подождать отображения ошибки. Это может сильно замедлить процесс разработки. Eclipse устраняет эту проблему.

    Как большинство других языков программирования, Java поддерживает комментарии, являющиеся простыми строками, которые компилятор игнорирует при проверке синтаксиса. Java поддерживает несколько вариантов комментариев:

    Последний вариант наиболее интересен. В двух словах, javadoc — это программа, поставляемая вместе с дистрибутивом Java SDK, которая может помочь вам сгенерировать HTML-документ для вашего кода. Вы можете сгенерировать документацию для ваших собственных классов, которая выглядит почти также, как и интерактивная документация по Java API. Если вы закомментируете ваш код соответствующим образом, то сможете выполнить программу javadoc из командной строки. Вы можете найти инструкции и всю доступную информацию по javadoc на Web-сайте Java Technology.

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

    abstract boolean break byte
    case catch char class
    const continue char class
    default do double else
    extend false final finally
    float for goto if
    implements import int instanceof
    interface long int native
    new null package private
    protected public package private
    static strictfp super switch
    synchronized short super this
    throw throws true try
    transient return void volatile
    while assert true false
    null

    Это не очень большой список, и Eclipse отображает зарезервированные слова жирным шрифтом при их вводе, поэтому вы даже не должны их запоминать. Все слова, кроме трех последних, являются ключевыми словами языка Java. Последние три слова — это зарезервированные слова. Для наших целей между ними нет разницы; вы не можете использовать ни те, ни другие.

    Теперь немного реального кода.

    Как я говорил ранее, экземпляр Adult знает свое имя, возраст, национальность и пол. Мы можем добавить эти данные к нашему классу Adult , объявляя их как переменные. Тогда каждый экземпляр класса Adult будет содержать их. Вероятнее всего, каждый экземпляр Adult будет иметь различные значения этих переменных. Вот почему переменные каждого объекта часто называются переменными экземпляра — они различны для каждого экземпляра класса. Давайте добавим их, используя в качестве спецификатора доступа ключевое слово protected :

    Теперь каждый экземпляр Adult будет содержать эти данные. Обратите внимание на то, что каждая строка кода заканчивается точкой с запятой. Это требование языка Java. Также отметим, что каждая переменная имеет тип данных. У нас есть одно целочисленная и три строковых переменных. Типы данных для переменных могут быть одной из двух разновидностей:

    • Примитивные типы данных.
    • Объекты (либо определенные пользователем, либо внутренние для языка Java), известные также как ссылочные переменные.

    Существует девять примитивных типов данных, с которыми вы, вероятнее всего, регулярно будете сталкиваться:

    Значение по умолчанию

    boolean N/A false true byte 8 bits 2 char 16 bits ‘u/0000’ ‘a’ short 16 bits 12 int 32 bits 123 long 64 bits 9999999 float 32 бит с десятичной точкой 0.0 123.45 double 64 бит с десятичной точкой 0.0 999999999.99999999

    Мы использовали int для переменной age , потому что нам не нужны десятичные значения, а тип int достаточно большой для хранения любого реального возраста человека. Мы использовали String для остальных трех переменных, поскольку они не являются цифровыми. String — это класс из пакета java.lang , к которому вы можете обратиться в своем Java-коде автоматически в любое время (мы поговорим об этом подробнее в разделе «Строки»). Вы можете объявить также и определенный пользователем тип переменных, например Adult .

    Мы определили каждую переменную в отдельной строке, но это не обязательно. Если у вас есть две или более переменных одного типа, вы можете определить их в одной строке, разделив запятыми, например:

    Если бы мы захотели инициализировать эти переменные при их объявлении, то могли бы просто добавить инициализацию после каждого названия переменной:

    Теперь наш класс знает о себе, и мы можем доказать это, что и сделаем в следующем разделе.

    Существует специальный метод, который вы можете включить в любой класс, для того чтобы JRE мог выполнить код. Он называется main() . Каждый класс может иметь только один метод main() . Естественно, не каждый класс будет его иметь, но поскольку Adult — это единственный класс, который пока у нас есть, добавим к нему метод main() , для того чтобы можно было создать экземпляр класса Adult и проверить его переменные экземпляра:

    В теле метода main() мы создали экземпляр класса Adult , затем распечатали значения переменных экземпляра. Посмотрите на первую строку. Это та ситуация, когда сторонники объектно-ориентированного кода критикуют язык Java. Они говорят, что new должен быть методом Adult , и вы, соответственно, должны вызывать его так: Adult.new() . Я, безусловно, принимаю их точку зрения, но язык Java не работает таким способом, и это один из случаев, когда сторонники ООП могут справедливо заявлять, что это не чистый объектно-ориентированный код. Снова посмотрите на первую строку. Вспомните, что каждый Java-класс имеет конструктор по умолчанию, который мы здесь и использовали.

    После создания экземпляра Adult мы сохраняем его в локальной переменной под названием myAdult. Затем распечатываем значения его переменных экземпляра. Почти в каждом языке программирования вы можете распечатать что-либо на консоль. Язык Java не исключение. В Java вы делаете это при помощи вызова метода println() потока out объекта System . Не беспокойтесь о том, что пока не понимаете подробностей процесса. Просто знайте, что мы используем вспомогательный метод для вывода информации. В каждом вызове мы передаем строку символов и соединяем ее со значением переменной экземпляра myAdult . Мы рассмотрим этот метод подробно позже.

    Для выполнения этого кода вам осталось сделать в Eclipse совсем немного. Выберите класс Adult в виде Types и нажмите на пиктограмму «бегущий человек» в панели инструментов. Должно появиться диалоговое окно Run, которое позволит вам создать конфигурацию для запуска вашей программы. Выберите Java Application в качестве типа конфигурации, которую вы хотите создать, и нажмите New . Eclipse укажет «Adult» как имя по умолчанию для конфигурации, что нам подходит. Нажмите Run для просмотра результатов. Eclipse отобразит вид Console ниже редактора кода; она должна выглядеть примерно так, как показано на рисунке 5.

    Рис. 5. Результаты выполнения программы

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

    Переменная Значение
    name «Bob»
    age 25
    race «inuit»
    gender «male»

    Запустите код повторно, нажав на пиктограмму «бегущий человек». Вы должны увидеть на консоли новые значения.

    Теперь сделаем наш объект Adult способным рассказать другим объектам о своих данных.

    Добавление поведения

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

    Методы доступа аналогичны всем остальным методам, но они обычно придерживаются специальных соглашений по наименованию. Для предоставления значения переменной экземпляра другому объекту создайте метод с названием getVariableName(). Таким же образом для разрешения другим объектам установки значений переменных экземпляра создайте метод с названием setVariableName() .

    В Java-сообществе эти методы доступа обычно называются методами getter и setter, поскольку их названия начинаются с get и set . Они представляют собой простейшие методы, которые вы когда-либо увидите, поэтому они являются хорошими кандидатами для иллюстрации основных концепций методов. Вы должны знать, что методы доступа являются общим понятием для методов, которые получают информацию об объекте. Не все методы доступа следуют соглашениям по наименованию для методов getter и setter, что мы увидим далее.

    Вот некоторые общие характеристики методов getter и setter:

    • Спецификатором доступа для методов getter и setter обычно является public .
    • Методы getter обычно не используют какие-либо параметры.
    • Методы setter обычно принимают параметры и часто только один, который является новым значением переменной экземпляра, которую они устанавливают.
    • Возвращаемый тип данных метода getter обычно такой же, что и тип переменной экземпляра, значение которой он возвращает.
    • Возвращаемый тип данных метода setter обычно равен void . Это означает, что они ничего не возвращают (они только устанавливают значение переменной экземпляра).

    Мы можем добавить методы доступа для переменной экземпляра age объекта Adult следующим образом:

    Метод getAge() возвращает значение переменной age при помощи ключевого слова return . В методах, которые не возвращают результат, последним оператором является return void; . В данном методе getter мы ссылаемся на age по ее имени.

    Мы также могли использовать оператор return this.age; . Переменная this ссылается на текущий объект. Она подразумевается, когда вы ссылаетесь на переменную экземпляра напрямую. Некоторые ОО-программисты из мира Smalltalk предпочитают использовать this всегда, когда ссылаются на переменную экземпляра, точно так же, как они использовали ключевое слово self при кодировании в Smalltalk. Я и сам люблю так поступать, но в языке Java это не требуется (и при этом на экран добавляется дополнительная информация), поэтому в примерах данного руководства мы не будем использовать этот прием до тех пор, пока код без него станет менее понятным.

    Теперь, когда у нас есть методы доступа, мы должны заменить прямой доступ к переменной age в нашем методе main() на вызов метода. main() теперь должен выглядеть следующим образом:

    Если вы выполните этот код снова, результаты должны быть такими же, что и раньше. Обратите внимание на то, что вызвать метод объекта легко. Используйте следующую форму:

    Если метод не принимает параметры (как наш метод getter), вы все равно должны добавить круглые скобки после имени вызываемого метода. Если метод принимает параметры (как наш метод setter), укажите их внутри круглых скобок, разделяя запятыми в том случае, если их больше одного.

    Пару слов о методе setter перед продолжением работы: Он принимает параметр int с названием anAge . Затем присваивает значение этого параметра переменной экземпляра age . Мы могли бы назвать параметр как угодно. Имя не важно, но, используя этот параметр внутри метода, вы должны применять именно указанное вами имя.

    Перед продолжением работы давайте попробуем использовать метод setter . Добавьте следующую строку в метод main() сразу после создания экземпляра Adult :

    Теперь выполним код опять. Результат должен быть равен 35. Вот что происходило за кулисами:

    • Мы передали целочисленное значение в метод в качестве параметра.
    • JRE выделил оперативную память для параметра и назвал его anAge .

    Методы доступа полезны, но мы хотим, чтобы наши объекты Adult могли выполнять что-либо еще, кроме как использовать совместно с другими свои данные, поэтому мы должны добавить другие методы. Мы хотим, чтобы наш объект Adult мог что-нибудь сказать, поэтому давайте создадим сейчас метод speak() :

    Пока синтаксис должен быть вам знаком. Метод возвращает строку символов. Давайте используем его и очистим метод main() . Измените первый вызов println() на:

    Повторите выполнение кода. Вы должны увидеть слово hello на консоли.

    Мы использовали несколько переменных с типом String , но до сих пор их не рассмотрели. Обработка строк в языке C трудоемка, поскольку они являются массивами 8-битных символов, заканчивающимися нулевым символом, которыми вы должны были управлять. В языке Java строки — это первоклассные объекты типа String , имеющие методы, которые помогут вам их обрабатывать. Что касается строк из C-мира, то наиболее похожим Java-кодом является примитивный тип данных char , который хранит один символ в кодировке Unicode, например ‘a’ .

    Вы уже видели, как создать экземпляр объекта String и установить его значение, но существуют и другие способы сделать это. Вот несколько способов создания экземпляра String со значением «hello»:

    Поскольку строки в языке Java являются объектами, вы можете использовать оператор new для создания экземпляра. Установка переменной типа String приведет к этому же результату, поскольку Java создает объект String для хранения символов, затем присваивает этот объект переменной экземпляра.

    Вы можете сделать многое с переменными String ; класс имеет большое число полезных методов. Даже не используя методы, мы уже делали кое-что интересное с переменными String путем соединения пары строк:

    Вместо использования + мы могли бы вызвать метод concat() String для соединения ее с другой строкой:

    Этот код может выглядеть немного странным, поэтому давайте рассмотрим его вкратце, слева направо:

    • System — это встроенный объект, который позволяет вам взаимодействовать с различными сущностями системной среды (в том числе и с некоторыми собственными возможностями Java-платформы).
    • out — это переменная класса в System . Это означает, что она доступна без создания экземпляра System . Она представляет консоль.
    • println() — это метод out , принимающий параметр String , отображающий его на консоли и завершающий отображение символом новой строки.
    • «Name: » — это строка символов. Java-платформа обрабатывает этот литерал как экземпляр String , поэтому мы можем вызывать его методы напрямую.
    • concat() — это метод экземпляра String , который принимает параметр String и соединяет его со строкой, чей метод вы вызвали.
    • myAdult это наш экземпляр Adult.
    • getName() — это метод доступа для name переменной экземпляра.

    Итак, JRE берет имя нашего объекта Adult , вызывает в нем метод concat() и добавляет «Bob» к «Name: «.

    В Eclipse вы можете увидеть все доступные методы любого объекта, поместив вашу точку вставки после точки, которая следует за переменной, содержащей экземпляр, и нажав затем Ctrl-Spacebar. При этом отобразится список методов объекта, находящегося слева от точки. Вы можете пролистать список (он свернут) при помощи стрелок управления курсором на вашей клавиатуре, выделить желаемый метод и нажать Enter для его выбора. Например, для просмотра всех методов, доступных для объектов String , поместите вашу точку вставки после точки, следующей после «Name: «, и нажмите Ctrl-Spacebar.

    Теперь давайте используем соединение строк в нашем классе Adult . До сих пор мы имели переменную экземпляра name . Неплохо было бы иметь firstname и lastname , затем объединить их, когда кто-либо запрашивает у Adult его имя. Нет проблем! Добавьте следующий метод:

    Eclipse должен был показать красные волнистые линии в методе, поскольку эти переменные экземпляра еще не существуют. Это означает, что код не может быть откомпилирован. Теперь замените существующую переменную экземпляра name двумя следующими (со значениями по умолчанию они имеют больший смысл):

    Затем замените первый вызов println() следующим вызовом:

    Теперь у нас есть более симпатичный метод getter для наших переменных. Он соединяет их для создания полного имени Adult . Мы могли бы также записать getName() следующим образом:

    Этот код делает то же самое, но демонстрирует явное использование метода String и построение цепочки вызовов методов. Когда мы вызываем concat() для firstname со строкой символов (пробел), метод возвращает новый объект String , являющийся их комбинацией. Затем мы сразу же вызываем метод concat() этого нового объекта для соединения с lastname . В результате получаем красиво отформатированное полное имя.

    Наш объект Adult может говорить (метод speak), но не может двигаться (move). Давайте добавим поведение для «перемещения».

    Прежде всего, добавим переменную экземпляра для отслеживания количества шагов, сделанных объектом Adult :

    Теперь добавим метод с названием walk() :

    Наш метод принимает целочисленный параметр, указывающий количество шагов, которые нужно сделать, обновляет переменную progress, хранящую это количество шагов, и отображает на экране некоторые результаты. Также хорошо было бы добавить метод getter для переменной progress ; setter не нужен. Почему? Действительно, разрешать другому объекту телепортировать нас вперед на некоторое количество шагов, возможно, не такая хорошая идея. Если другой объект хочет указать нам переместиться, он может вызвать walk() . Это, безусловно, законный вызов, хотя наш пример и является тривиальным. В реальном проекте такие решения по дизайну приложения должны приниматься постоянно, и часто их нельзя предусмотреть, независимо от того, что говорят гуру объектно-ориентированного дизайна (ООД).

    В нашем методе мы обновляем переменную progress , добавляя к ней значение steps . Мы опять сохраняем результат в progress . Мы использовали самый общий оператор присваивания = для сохранения результата. Арифметический оператор + мы применили для сложения значений. Существуют другие способы достичь этой же цели. Следующий код делает то же самое:

    Применение оператора присваивания += немного менее неуклюже, чем применение оператора = в нашем первом варианте. Это предохраняет нас от использования ссылки на переменную progress дважды. Но происходит то же самое: добавляется значение steps к переменной progress и результат сохраняется в progress .

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


    Оператор Использование
    + a + b Добавляет a и b
    + +a Преобразовывает a к типу int , если эта переменная имела тип byte , short или char
    a — b Вычитает b из a
    -a Арифметическое отрицание a
    * a * b Умножает a и b
    / a / b Делит a на b
    % a % b Возвращает остаток от деления a на b
    (другими словами, это оператор взятия по модулю)
    ++ a++ Увеличивает a на 1 ; использует для вычисления значение переменной a перед увеличением
    ++ ++a Увеличивает a на 1 ; использует для вычисления значение переменной a после увеличения
    a— Уменьшает a на 1 ; использует для вычисления значение переменной a перед уменьшением
    —a Уменьшает a на 1 ; использует для вычисления значение переменной a после уменьшения
    += a += b Аналогично a = a + b
    -= a -= b Аналогично a = a — b
    *= a *= b Аналогично a = a * b
    %= a %= b Аналогично a = a % b

    Мы также уже встречали и другие обозначения, которые называются операторами в языке Java. Например: . (точка), которая определяет названия пакетов и вызывает методы; ( params ) , который разделяет запятыми список параметров метода; new , который вместе с именем конструктора создает экземпляр объекта. В следующем разделе мы встретим несколько других операторов.

    Условное выполнение

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

    Язык программирования Java предоставляет некоторые операторы и некоторые выражения по управлению потоком выполнения для того, чтобы вы могли принимать решения в вашем коде. Наиболее часто решение в коде начинается с булевого выражения (которое имеет значение истинно (true) или ложно (false)). Эти выражения используют операторы отношения, которые сравнивают один операнд или выражение с другим, и условные операторы. Вот их список:

    Возвращает true , если.

    Оператор
    > a > b a больше b
    >= a >= b a больше или равно b
    a a меньше b
    a a меньше или равно b
    == a == b a равно b
    ! = a != b a не равно b
    && a && b a и b оба имеют значение true , b вычисляется условно
    (если значение a равно true , нет необходимости вычислять b )
    // a // b a или b имеют значение true , b вычисляется условно
    (если значение a равно true , нет необходимости вычислять b )
    ! ! a значение a равно false
    & a & b a и b оба имеют значение true , всегда вычисляется b
    / a / b a или b имеют значение true , всегда вычисляется b
    ^ a ^ b a и b имеют разные значения ( true , если значение a равно true , а значение b равно false ,
    и наоборот, но не тогда, когда оба имеют значение true , или оба имеют значение false )

    Теперь мы должны использовать эти операторы. Давайте добавим простую логику к нашему методу walk() :

    Теперь логика в методе проверяет, насколько большим является значение steps . Если оно слишком большое, метод возвращает управление немедленно и говорит о том, что значение слишком велико. Каждый метод может вернуть управление только один раз. Но разве здесь не два оператора return ? Да, но выполняться будет только один. Условный оператор Java if имеет следующую форму:

    Фигурные скобки необязательны, если после if и/или else идет одиночное выражение; вот почему в нашем коде они не используются. Не обязательно наличие и выражения else ; у нас его нет. Мы могли бы поместить оставшийся код метода в выражение else , но результат работы был бы тот же, просто в код добавились бы так называемые необязательные синтаксические украшения, которые уменьшают читаемость кода.

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

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

    Область видимости переменной простирается до конца секции (или блока) кода, в котором она была объявлена. Например, в нашем методе walk() мы обращаемся к параметру steps по его имени, поскольку он находится в области видимости. Вне метода ссылка на steps вызвала бы ошибку компилятора. Код может также ссылаться на переменную, объявленную в более широкой области видимости, чем текущее положение в коде. Например, мы можем обращаться к переменной экземпляра progress внутри метода walk() .

    Мы можем сделать условную проверку более привлекательной, используя другую форму выражения if :

    Наш метод мог бы выглядеть следующим образом:

    Существует также краткая версия выражения if , которая выглядит немного странно, но выполняет ту же задачу, хотя и не позволяет применять несколько операторов ни в части if , ни в части else . В этой версии используется тернарный оператор ?: (тернарным называется оператор, работающий с тремя операндами). Мы могли бы переписать наше простое условие if следующим образом:

    Но это не выполнило бы нашу задачу, поскольку, если значение steps меньше 100, мы хотим возвратить сообщение и обновить переменную progress . Поэтому в данном случае использование сокращенного оператора ?: не подходит, так как мы не могли бы выполнить несколько выражений.

    Выражение if является только одним из выражений, которые позволяют вам проверять условия в вашем коде. Другим выражением, которое встречается часто, является выражение switch . Оно вычисляет целочисленное выражение, затем выполняет одно или больше выражений в зависимости от значения этого выражения. Его синтаксис обычно такой:

    JRE вычисляет целочисленное выражение, выбирает подходящий вариант (case) и выполняет выражения этого варианта. Последним выражением каждого варианта, за исключением последнего, является break; . Оно «прерывает» выражение switch и управление передается в следующую за ним строку кода. Технически не требуется ни одно из выражений break; . Последнее выражение особенно не обязательно, поскольку управление все равно будет передаваться в следующую строку кода. Но хорошей практикой является включение этих выражений. Если вы не вставите break; в каждом case , выполнение программы будет продолжено в следующем case , и так далее до тех пор, пока не встретится break; или не встретится конец выражения. Вариант default выполняется тогда, когда целочисленное значение не подходит ни к одному из вариантов. Это выражение не обязательно.

    По существу, выражение switch является выражением if-else с целочисленным условием; если ваше условие основано на одном целочисленном значении, вы можете использовать любой тип выражения. Нужно ли нам переписывать выражение if в методе walk() в виде выражения switch ? Нет, поскольку мы проверяем булево выражение (steps > 100). Это не разрешается в switch .

    Ниже приведен тривиальный пример использования выражения switch (это классический пример):

    month — это целочисленное выражение, представляющее номер месяца. Поскольку оно имеет целый тип, использование выражения switch корректно. Для каждого правильного варианта мы выводим название месяца, затем прерываем ( break ) выражение. Вариант default обрабатывает номера месяцев, выходящих за диапазон корректных номеров месяцев.

    Наконец, вот пример того, как использование перехода на следующий вариант может быть красивым приемом:

    Здесь мы видим, что варианты 2, 3 и 9 обрабатываются одним способом, а оставшиеся варианты — другим. Обратите внимание на то, что варианты не обязательно должны идти по порядку, и что переход в следующий вариант мы в данном случае использовали с пользой.

    В начале данного руководства мы все делали без использования условий, что в определенной мере хорошо, но имеет свои ограничения. Аналогично, иногда нужно выполнить какое-либо действие повторно, до тех пор, пока не будет выполнена какая-нибудь работа. Например, предположим, что мы хотим сказать больше, чем просто «hello» в нашем объекте Adult . Это относительно просто сделать в Java-коде (хотя это не так просто, как в языках-сценариях, например Groovy). Язык Java предоставляет несколько способов для итерации по коду или для повторного выполнения:

    • выражения for
    • выражения do
    • выражения while

    Они известны под общим названием — циклы (например, «цикл for «), поскольку они повторяют фрагмент кода до тех пор, пока вы не укажете остановиться. В следующих нескольких разделах мы кратко рассмотрим каждый из циклов и используем их, для того чтобы сделать наш метод speak() более словоохотливым.

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

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

    Изменим наш метод speak() таким образом, чтобы он выводил выражение «hello» три раза, используя цикл for . Одновременно мы изучим встроенный Java-класс, который делает объединение строк простой задачей:

    Класс StringBuffer из пакета java.lang позволяет легко манипулировать строками и прекрасно подходит для добавления строк (это то же самое, что и объединение строк). Мы просто создаем экземпляр этого класса, затем вызываем метод append() каждый раз, когда нужно добавить что-либо к speech . Реальная работа происходит в цикле for . В круглых скобках цикла мы объявляем целочисленную переменную i для работы в качестве счетчика цикла (в качестве счетчиков цикла очень часто используются символы i, j и k, хотя вы можете использовать любое имя переменной). Следующее выражение говорит о том, что мы будем выполнять цикл до тех пор, пока значение счетчика цикла не достигнет величины 3. Следующее выражение говорит о том, что мы увеличиваем наш счетчик на единицу после каждого цикла (помните оператор ++ ?). В каждом цикле мы вызываем append() объекта speech и добавляем в конец еще одно выражение «hello».

    Теперь замените наш старый метод speak() на новый, удалите все выражения println из main() , и добавьте одно выражение, в котором вызывается метод speak() объекта Adult . В результате вы должны получить следующий класс:

    После его выполнения вы должны получить на консоли выражение hellohellohello . Но использование for — это только один из способов выполнить эту работу. Язык Java предоставляет еще два варианта, которые мы рассмотрим далее.

    Сначала мы попробуем цикл while . Следующая версия метода speak() выполняет ту же работу, что и рассмотренная в предыдущем разделе версия:

    Общий синтаксис цикла while :

    Цикл while выполняет код своего блока до тех пор, пока его выражение не возвратит значение false . Как же управлять циклом? Вы должны гарантировать, что это выражение станет ложным в какой-то момент времени; в противном случае ваш цикл будет бесконечным. В нашей ситуации мы объявили локальную переменную i вне цикла, присвоили ей значение 0, затем проверили ее значение в выражении цикла. В каждом цикле мы увеличиваем переменную i. Когда ее значение становится не меньше 3, цикл завершается, и мы возвращаем String , хранящийся в нашем буфере.

    Здесь мы видим, что цикл for удобнее. В версии с циклом for мы объявили и инициализировали нашу управляющую переменную, проверяли ее значение и увеличивали ее в одной строке кода. В версии с циклом while требуется больше вспомогательной работы. Если мы забудем увеличить счетчик, цикл станет бесконечным. Если мы не проинициализируем счетчик, компилятор выдаст предупреждение. Но версия с циклом while может быть очень полезна, если нужно проверять сложное булево выражение (заключение его в однострочный цикл for может затруднить чтение).

    Мы рассмотрели циклы for и while , но в следующем разделе мы продемонстрируем, что есть еще и третий вариант.

    Следующий код делает ту же самую работу, что и два рассмотренных нами ранее цикла:

    Общий синтаксис циклов do :

    Цикл do фактически такой же, что и цикл while , за исключением того, что он проверяет свое булево выражение после каждого выполнения тела цикла. Что происходит в цикле while , если выражение имеет значение false при первой же проверке? Цикл не будет выполнен ни разу. Цикл do гарантирует, что цикл выполнится хотя бы один раз. Иногда это различие может быть важным.

    Перед завершением работы с циклами рассмотрим два выражения ветвления, которые могут быть полезны. Мы уже встречались с выражением break при работе с выражениями switch . В циклах они производят такой же эффект — останавливают цикл. Выражение continue , с другой стороны, останавливает текущую итерацию цикла и сразу выполняется следующая итерация. Вот тривиальный пример:

    Если вы поместите этот код в ваш метод main() и запустите его, то получите следующие результаты:

    В первых двух прохождениях цикла переменная i меньше значения 2, поэтому выводится сообщение «Haven’t hit 2 yet. «, затем выполняется выражение continue , которое вызывает следующую итерацию цикла. Когда i равно 2, код в первом выражении if не выполняется. Мы попадаем во второй if , отображаем сообщение «Hit 2. «, затем прекращаем ( break ) цикл.

    Рассмотрев в следующем разделе обработку коллекций, мы усложним поведение.

    Коллекции

    Большая часть реальных приложений имеет дело с коллекциями чего-либо (файлов, переменных, строк файлов и т.д.). Часто объектно-ориентированные программы работают с коллекциями объектов. Язык Java имеет усовершенствованную библиотеку Collections Framework, которая позволяет вам создавать и управлять коллекциями объектов различных типов. Эта библиотека сама может занять целое руководство, поэтому здесь мы не будем рассматривать ее всю. Вместо этого мы рассмотрим одну очень широко используемую коллекцию и некоторые способы ее применения. Эти способы подходят для большинства коллекций, доступных в языке Java.

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

    Существует два способа объявления массива:

    • Создать его с определенным размером, который является фиксированным.
    • Создать его с определенным набором начальных значений. Размер этого набора определяет размер массива — он будет ровно таким, чтобы быть достаточным для хранения этих значений. Опять же, этот размер является фиксированным.

    В общем случае массив объявляется следующим образом:

    Создать целочисленный массив из пяти элементов можно двумя способами:

    Первое выражение создает пустой массив из пяти элементов. Второе выражение создает инициализированный массив. Между фигурными скобками можно указать список начальных значений, разделенных запятыми. Обратите внимание на то, что мы не указали размер массива в квадратных скобках — количество элементов нашего блока инициализации устанавливает размер массива в пять элементов. Это проще, чем создать массив, а затем закодировать цикл для присвоения значений его элементам, например, так:

    Этот код также объявляет целочисленный массив из пяти элементов. Если вы попытаетесь поместить более пяти элементов в массив, у вас возникнут проблемы при выполнении кода. Для загрузки массива мы выполняем цикл от 1 до длины массива, которую мы определяем при помощи метода length() . В каждом цикле мы помещаем целое число в массив. После помещения пятого элемента цикл прекращается.

    После загрузки нашего массива мы можем обращаться к его элементам в аналогичном цикле:

    Представляйте массив как последовательность ячеек памяти. Каждый элемент в массиве занимает одну ячейку памяти, которой назначен индекс при создании массива. Вы можете обратиться к элементу в конкретной ячейке так:

    Индексы массива отсчитываются с нуля; это означает, что первый элемент имеет индекс 0. Теперь наш цикл имеет смысл. Мы начинаем цикл с нуля, поскольку массив начинается с нуля, и проходим по каждому элементу массива, отображая его значение.

    Массивы хороши, но работать с ними немного не удобно. Их загрузка требует усилий, а после объявления массива вы можете загрузить в него только значения определенного типа и только определенное количество элементов, которое может поместиться в массиве. Определенно, массивы не являются слишком объектно-ориентированными. Фактически, присутствие массивов в языке Java является пережитком времен до объектно-ориентированного программирования. Они применяются в программном обеспечении повсеместно, поэтому их отсутствие в языке могло бы затруднить его существование в реальном мире, особенно при необходимости взаимодействия со старыми системами, использующими массивы. Однако язык Java предоставляет вам намного больше инструментов для обработки коллекций элементов. Эти инструменты являются абсолютно объектно-ориентированными.

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

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

    Для использования ArrayList в вашем коде вы должны добавить выражение import для него в вашем классе:

    Пустой ArrayList объявляется так:

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

    Коллекции Java хранят объекты, а не примитивы. Массивы могут хранить и то, и другое, но они чаще всего не объектно-ориентированы, как мы того хотим. Если вы хотите записать в список что-либо, являющееся подтипом Object , вы просто вызываете для этого один из различных методов ArrayList . Простейшим методом является:

    Он добавляет объект в конец списка. Чем дальше, тем лучше. Но что случится, если вы захотите добавить примитивный тип в список? Вы не можете сделать это напрямую. Вместо этого вы должны заключить примитивы в объекты. Существует один класс-конверт (wrapper class) для каждого примитивного типа:

    • Boolean для boolean s
    • Byte для byte s
    • Character для char s
    • Integer для int s
    • Short для short s
    • Long для long s
    • Float для float s
    • Double для double s

    Например, для помещения примитивного типа int в ArrayList , мы должны были бы использовать следующий код:

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

    Большинство подростков в реальном мире носят с собой некоторое количество денег. Предположим, что каждый объект Adult имеет кошелек, в котором содержатся деньги. В данном руководстве мы предполагаем, что:

    • Деньги представлены только банкнотами.
    • Номинальная стоимость банкноты (как целое число) идентифицирует каждую банкноту.
    • Все деньги в кошельке являются долларами США.
    • Каждый объект Adult начинает свою «запрограммированную» жизнь без денег.

    Помните наш массив целых чисел? Давайте вместо него использовать ArrayList . Добавьте выражение import для ArrayList , затем добавьте ArrayList к вашему классу Adult в конце списка других переменных экземпляра:

    Мы создали ArrayList и инициализировали его как пустой список, поскольку объект Adult должен заработать каждый доллар. Мы можем добавить также некоторые методы доступа к переменной wallet :

    Предоставляемые вами методы доступа являются законным вызовом. В данном случае мы применили типичные. Нет причин, почему бы мы не могли вызвать setWallet() также как resetWallet() , или даже goBankrupt() , поскольку мы сбрасываем его в пустой ArrayList . Должен ли другой объект уметь менять наш кошелек на новый? Опять же, законный вызов. Ведь это и есть принципы ООД!

    Теперь добавим несколько методов, позволяющих нам взаимодействовать с нашей переменной wallet :

    В следующих двух разделах мы более подробно рассмотрим их.

    Метод addMoney() позволяет нам добавить банкноту в наш кошелек. Вспомните, что наши «банкноты» представляют собой простые целые числа. Для добавления их в нашу коллекцию мы заключаем int в Integer .

    Метод spendMoney() тоже работает с упаковкой для проверки наличия банкноты в нашем кошельке, вызывая метод contains() . Если она есть, мы вызываем remove() для ее извлечения. Если нет, мы говорим об этом.

    Давайте применим эти методы в main() . Замените его текущее содержимое на следующий код:

    В методе main() скомбинировано много действий, о которых мы уже знаем. Прежде всего, мы вызываем addMoney() несколько раз для помещения денег в кошелек. Затем в цикле проверяем содержимое кошелька и выводим эту информацию. Для этого используем цикл while , но необходимо выполнить некоторую дополнительную работу. Мы должны:

    • Получить Iterator для списка, который позволит нам обращаться к элементам в списке.
    • Вызвать метод hasNext() объекта Iterator в качестве булевого выражения нашего цикла для того, чтобы определить, есть ли у нас еще элементы для обработки.
    • Вызвать метод next() объекта Iterator для получения следующего элемента каждый раз при прохождении цикла.
    • Привести тип (или преобразовать ) возвращаемого объекта в тип элементов, находящихся в списке (в данном случае Integer )

    Это стандартная процедура для прохождения по коллекции в языке Java. В качестве альтернативы, мы могли бы вызвать toArray() и получить массив, по которому мы могли бы пройти при помощи цикла for . Но более объектно-ориентированный способ — это использовать возможности библиотеки Java Collections.

    Единственной новой концепцией здесь является приведение типов. Что это такое? Как мы уже знаем, объекты в языке Java имеют тип или класс. Если вы посмотрите на сигнатуру метода next() , то увидите, что он возвращает Object , а не конкретный подкласс Object . Все объекты в мире Java-программирования являются подклассами Object , но язык Java должен знать конкретный тип объекта, для того чтобы вы могли вызывать методы, специфичные для типа, с которым работаете. Если вы не выполните приведение типа, то будете ограничены только методами, доступными для Object , которые составляют довольно небольшой список. В данном примере нам не нужно вызывать какие-либо методы класса Integer , но если бы мы делали это, то должны были бы сначала выполнить приведение типов.

    Усовершенствование вашего объекта

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

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

    По ходу дела мы изучим некоторые приемы рефакторинга и узнаем, как решать некоторые проблемы, возникающие при выполнении нашего кода.

    Мы говорили о конструкторах ранее. Вы, возможно, помните, что каждый объект вашего Java-кода автоматически получает конструктор по умолчанию, не принимающий аргументов. Вы не должны определять его и можете не увидеть его в коде. Фактически, мы воспользовались этим в нашем классе Adult . Здесь не видно конструктора.

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

    Определить конструктор без аргументов для Adult просто:

    Все. Наш конструктор без аргументов действительно не делает ничего, кроме создания Adult . Теперь при вызове new для создания Adult мы будем использовать наш конструктор без аргументов вместо конструктора по умолчанию. Но что если мы захотим, чтобы конструктор делал что-нибудь? В случае с Adult могло бы быть очень удобным уметь передавать фамилию и имя в виде объектов String и устанавливать в конструкторе наши переменные экземпляра в эти начальные значения. Это тоже сделать просто:

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

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

    При создании двух методов с одинаковым названием, но с разным количеством (или с разным типом) параметров, вы перегружаете этот метод. Это одна из мощных возможностей объектов. Система времени исполнения Java определит вызываемую версию метода в зависимости от того, что вы передали в качестве аргументов. В ситуации с нашими конструкторами, если мы не передадим какие-либо аргументы, JRE будет использовать конструктор без аргументов. Если мы передадим два объекта String , система времени исполнения будет использовать версию, принимающую два параметра String . Если мы передадим аргументы другого типа (или один объект String ), система времени исполнения выдаст предупреждение о том, что не доступен конструктор, принимающий эти типы.

    Вы можете перегрузить любой метод, не только конструкторы, что облегчает создание удобного интерфейса для пользователей ваших классов. Давайте попробуем добавить еще одну версию нашего метода addMoney() . Сейчас этот метод принимает один аргумент типа int . Это хорошо, но что если мы захотим добавить $100 в кошелек Adult ? Мы должны были бы вызвать метод столько раз, сколько необходимо для добавления конкретного набора банкнот, сумма которых составляет $100. Это очень неудобно. Было бы намного проще передать массив int , представляющий набор банкнот. Поэтому давайте перегрузим метод для приема параметра типа массив. Вот метод, который у нас уже имеется:

    Вот его перегруженная версия:

    Этот метод очень похож на другой наш метод addMoney() , но он принимает массив в качестве параметра. Давайте попробуем использовать его, изменив наш метод main() следующим образом:

    После запуска кода на выполнение мы можем увидеть, что в кошельке нашего объекта Adult пока имеется $16. Это намного более удобный интерфейс. Видите ли вы какое-либо дублирование кода в наших двух методах? Две строки в первой версии являются копиями строк во второй версии. Если бы мы хотели изменить действия при добавлении денег, то должны были бы изменить код в двух местах, что не очень хорошо. Если бы мы добавили еще одну версию метода, принимающую в качестве параметра ArrayList вместо массива, то должны были бы изменить код в трех местах. Это быстро стало бы неприемлемым. Вместо этого мы можем выполнить рефакторинг кода для устранения дублирования. В следующем разделе мы выполним рефакторинг под названием Extract Method для завершения работы.

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

    Прежде всего, мы должны создать метод, содержащий две строки дублированного кода. Назовем его addToWallet() :

    Мы сделали этот метод защищенным, поскольку это действительно наш собственный внутренний вспомогательный метод, а не часть открытого интерфейса нашего класса. Теперь заменим эти строки кода в наших методах вызовом нового метода:

    Вот перегруженная версия:

    Если вы опять выполните код, вы увидите те же самые результаты. Такой тип рефакторинга должен стать привычным. Eclipse облегчает работу при помощи нескольких встроенных видов автоматического рефакторинга. Их подробное обсуждение выходит за рамки данного руководства, но вы можете поэкспериментировать с ними. Если бы мы выделили эти две строки дублированного кода, допустим в первой версии addMoney() , то могли бы щелкнуть правой кнопкой мыши по выделенному тексту и выбрать Refactor>Extract Method . Тогда Eclipse мог бы провести нас через процесс рефакторинга в пошаговом режиме. Это одна из наиболее мощных возможностей IDE.

    Методы и переменные, которые мы имеем в классе Adult , являются методами и переменными экземпляра. Каждый экземпляр будет их иметь.

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

    • Каждый экземпляр класса совместно использует одну и ту же копию переменной класса.
    • Вы можете вызвать метод класса с самим классом, без наличия экземпляра.
    • Методы экземпляра могут обращаться к переменным класса, но методы класса не могут обращаться к переменным экземпляра.
    • Методы класса могут обращаться только к переменным класса.

    Когда имеет смысл добавить переменные класса или методы класса? Лучшее практическое правило — делать это редко, для того чтобы не злоупотреблять ими. Некоторыми обычными примерами их использования являются:

    • Объявление констант, которыми могут пользоваться любые экземпляры класса.
    • Отслеживание «счетчика» экземпляров класса.
    • Использование в классе со вспомогательными методами, которые для своей работы не требуют наличия экземпляра (например, метод Collections.sort()).

    Для создания переменной класса используйте ключевое слово static при ее объявлении:

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

    Например, мы использовали целые числа для описания «банкнот» в кошельке Adult . Это совершенно корректно, но, возможно, было бы правильнее поименовать целочисленные значения таким образом, чтобы мы при чтении кода легко видели, что означают числа. Объявим для этого несколько констант в том же месте, где мы объявили переменные экземпляра для нашего класса:

    По соглашению константы класса называются большими символами, отдельные слова констант разделяются знаками подчеркивания. Мы использовали ключевое слово static для объявления их в качестве переменных класса и добавили ключевое слово final , чтобы гарантировать невозможность их изменения каким-либо экземпляром (то есть, сделать их константами). Теперь мы можем изменить метод main() для добавления денег в наш объект Adult при помощи этих новых констант:

    При чтении кода очевидно, что мы добавляем деньги в кошелек.

    Как мы уже видели, вызов метода экземпляра осуществляется следующим образом:

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

    Нам не нужен экземпляр для вызова этого метода. Для этого применяется сам класс. Используемый нами метод main() является методом класса. Взгляните на его сигнатуру. Обратите внимание на то, что он объявлен как public static . Мы видели этот спецификатор доступа прежде. Ключевое слово static указывает, что это метод класса, вот почему такие методы иногда называются статическими методами. Нам не нужен экземпляр Adult для вызова main() .

    Мы можем создать методы класса для Adult при желании, хотя в действительности нет причины делать это в данном случае. Хотя для демонстрационных целей добавим тривиальный метод класса:

    Закомментируйте имеющиеся строки кода в методе main() и добавьте следующие строки:

    После выполнения этого кода вы должны увидеть соответствующее сообщение, дважды отображенное на консоли. Первый вызов doSomething() является обычным способом вызова метода класса. Можно также вызвать его через экземпляр класса, как это сделано в третьей строке кода. Но это, в действительности, не очень хорошая практика. Eclipse предупредит об этом, подчеркнув эту строку желтой волнистой линией, и предложит обратиться к этому методу «статическим способом» через класс, а не через экземпляр.

    Существует два способа сравнить объекты в языке Java:

    Первый, наиболее употребляемый, сравнивает объекты на равенство. Другими словами, выражение:

    возвратит true тогда и только тогда, когда a и b ссылаются точно на тот же экземпляр класса (то есть, на тот же объект). Исключение составляют примитивы. При сравнении двух примитивов с использованием оператора == система времени исполнения Java сравнивает их значения (они не являются настоящими объектами). Попробуйте поместить этот код в main() и взгляните на результат, отображаемый в консоли:

    Первое сравнение возвращает true , поскольку сравниваются примитивы с одинаковыми значениями. Второе сравнение возвращает false , поскольку две переменные не ссылаются на один и тот же экземпляр объекта. Третье сравнение возвращает true , потому что две переменные теперь ссылаются на один и тот же экземпляр. Если сделать то же самое с нашим классом, мы тоже получим false , потому что adult1 и adult2 не ссылаются на один и тот же экземпляр.

    Сравнить объекты можно следующим образом:

    Метод equals() принадлежит типу Object , который является предком каждого класса в языке Java. Это означает, что любой созданный вами класс будет наследовать базовое поведение equals() от Object . Это базовое поведение не отличается от оператора == . Другими словами, по умолчанию эти два выражения используют оператор == и возвращают значение false :

    Посмотрите на метод spendMoney() класса Adult снова. Что происходит за кулисами, когда мы вызываем метод contains() нашей переменной wallet ? Язык Java использует оператор == для сравнения объектов в списке с указанным объектом. Если он находит соответствие, метод возвращает значение true ; в противном случае возвращается false . Поскольку мы сравниваем примитивы, он может найти соответствие, основанное на целочисленных значениях (помните, что оператор == сравнивает примитивы по их значению).

    Это хорошо для примитивов, но что если мы хотим сравнить содержимое объектов? Оператор == не сделает это. Для сравнения содержимого объектов мы должны перегрузить метод equals() класса, экземпляром которого является переменная a . Это означает, что нужно создать метод с точно такой же сигнатурой, что и у метода одного из ваших суперклассов, но реализовать метод по другому. Если сделать это, вы сможете сравнивать содержимое двух объектов, а не только проверять, ссылаются ли две переменные на один и тот же экземпляр.

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

    Первое сравнение возвращает значение false , поскольку adult1 и adult2 ссылаются на разные экземпляры Adult . Второе сравнение тоже возвращает значение false , поскольку реализация метода equals() по умолчанию просто проверяет, ссылаются ли обе переменные на один и тот же экземпляр. Но поведение equals() по умолчанию обычно не то, что мы хотим. Мы хотели бы сравнивать содержимое двух объектов Adult , чтобы узнать, одинаковые ли они. Для этого мы можем перегрузить equals() . Как видно из двух последних сравнений в приведенном выше примере, класс Integer перегружает метод так, что оператор == возвращает false , но оператор equals() сравнивает на равенство упакованные значения int . Мы сделаем что-то похожее для класса Adult в следующем разделе.

    Перегрузка метода equals() для сравнения объектов на самом деле требует от нас перегрузки двух методов:

    Мы перегрузим метод equals() следующим способом, который является обычным стилем в Java:

    • Если объект, который мы собираемся сравнивать, является самим этим объектом, то они очевидно равны, поэтому возвращаем true .
    • Проверяем для уверенности, что объект, который мы собираемся сравнивать, является экземпляром Adult (если нет, два объекта очевидно не одинаковы).
    • Приводим тип входного объекта к Adult , для того чтобы использовать его методы.
    • Сравниваем части двух объектов Adult , которые должны быть равны, для того чтобы два объекта считались «равными» (какое бы определение равенства мы ни использовали).
    • Если какие-либо из этих частей не равны, возвращаем значение false ; в противном случае возвращаем true .

    Обратите внимание на то, что мы можем сравнить возраст каждого объекта с помощью == , поскольку это примитивные значения. Для сравнения String мы используем equals() , поскольку этот класс перегружает метод equals() для сравнения содержимого объектов String (если бы мы использовали == , то получали бы false каждый раз, потому что два объекта String никогда не будут одним и тем же объектом). То же самое мы делаем и для ArrayList , поскольку он перегружает equals() для проверки того, что два списка содержат одинаковые элементы в одинаковом порядке. Это хорошо подходит для нашего простого примера.

    Когда бы вы ни перегрузили equals() , необходимо также перегрузить hashCode() . Объяснение причины этого выходит за рамки данного руководства, а пока просто знайте, что язык Java использует значение, возвращенное из этого метода, для помещения экземпляров вашего класса в коллекции, которые используют хэш-алгоритм размещения объектов (например HashMap ). Единственными практическими правилами для этого метода (кроме того, что он должен возвращать целое значение) являются два приведенные далее правила. Метод hashCode() должен возвращать:

    • Одно и то же значение для одного и того же объекта постоянно.
    • Одинаковые значения для одинаковых объектов.

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

    Класс Object имеет метод toString() , который наследует каждый создаваемый вами класс. Он возвращает представление вашего объекта в виде String и очень полезен для отладки. Чтобы увидеть действие метода toString() , реализованное по умолчанию, выполните следующий эксперимент в методе main() :

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

    Метод println() вызывает метод toString() объекта, переданного ему. Поскольку мы пока не перегрузили toString() , то получаем вывод информации по умолчанию, которой является ID объекта. Каждый объект имеет ID, но он не много скажет вам о самом объекте. Было бы лучше, если бы мы перегрузили toString() для выдачи красиво отформатированного содержимого нашего объекта Adult :

    Мы создаем StringBuffer для создания представления нашего объекта в виде String , затем возвращаем объект String . После выполнения этого примера на консоли должна отобразиться следующая красиво отформатированная информация:

    Это значительно удобнее и полезнее, чем загадочный ID объекта.

    Хорошо было бы, если бы в нашем коде никогда не было ошибок, но это маловероятно. Иногда все происходит не так, как мы предполагали, а иногда проблема хуже, чем просто выдача нежелательных результатов. Когда это происходит, JRE генерирует исключительную ситуацию. Язык имеет некоторые специальные выражения, позволяющие вам перехватить исключительную ситуацию и обработать ее соответствующим образом. Вот общий формат для этих выражений:

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

    Попробуйте провести следующий эксперимент в main() :

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

    Эта трассировка стека отображает тип исключительной ситуации и номер строки, в которой она возникла. Помните, что мы должны выполнить приведение типа при удалении Object из Collection . У нас есть коллекция элементов Integer , но мы пытаемся получить первый элемент при помощи метода get(0) (где 0 ссылается на индекс первого элемента в списке, потому что список начинается с нулевого индекса, аналогично массиву) и привести его к типу String . Система времени исполнения Java выводит предупреждение. Сейчас программа просто аварийно завершается. Давайте сделаем это завершение более изящным, обрабатывая исключительную ситуацию:

    Здесь мы перехватываем исключительную ситуацию и выводим красивое сообщение. В качестве альтернативы мы могли бы ничего не делать в блоке catch , а выводить красивое сообщение в блоке finally , но в этом не было необходимости. В некоторых случаях объект исключительной ситуации (обычно, но не обязательно, обозначаемый e или ex ) может предоставлять вам больше информации об ошибке, которая может помочь вам отобразить более подробную информацию или восстановить ситуацию.

    Язык Java поддерживает полную иерархию исключительных ситуаций. Это значит, что существует много типов исключительных ситуаций. На самом высоком уровне некоторые исключительные ситуации проверяются компилятором, а некоторые, называемые RuntimeException , — нет. Правилами языка предусмотрено, что вы должны перехватывать или указывать ваши исключительные ситуации. Если метод может сгенерировать отличную от RuntimeException исключительную ситуацию, он должен либо обработать ее, либо указать, что обработать ее должен вызывающий метод. Это делается при помощи указания выражения throws в сигнатуре метода. Например:

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

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

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

    Java-приложения

    Мы уже видели приложение, хотя и очень простое. Наш класс Adult имеет метод main() с самого начала. Он был необходим для того, чтобы система времени исполнения Java выполнила ваш код. Однако обычно ваши объекты не будут иметь методов main() . Java-приложения обычно состоят из:

    • Одного класса с методом main() , с которого начинается работа.
    • Набор других классов, выполняющих работу.

    Для демонстрации того, как это работает, мы должны добавить еще один класс в наше приложение. Этот класс будет «управляющим».

    Наш управляющий класс может быть очень простым:

    Выполните следующие действия для создания класса таким образом, чтобы он действительно «управлял» нашей программой:

    • Создайте класс в Eclipse при помощи той же кнопки «New Java Class» панели инструментов, которую мы использовали для создания Adult в разделе «Объявление класса».
    • Назовите класс CommunityApplication , и проверьте, что вы выбрали вариант для добавления метода main() в класс. Eclipse генерирует этот класс за вас, включая main() .
    • Удалите метод main() из класса Adult .

    Все, что осталось сделать, — поместить что-нибудь в наш новый метод main() :

    Создайте новую конфигурацию запуска в Eclipse так же, как мы делали это для класса Adult в разделе «Выполнение кода в Eclipse», и запустите его. Вы должны увидеть, что наш объект прошел 10 шагов.

    Сейчас мы имеем простое приложение, начинающееся в CommunityApplication.main() и использующее наш объект Adult . Конечно, приложения могут быть более сложными, чем рассмотренное здесь, но основная идея остается такой же. Не так уж и необычно для Java-приложений иметь сотни классов. После запуска работы первичным управляющим классом программа работает при помощи взаимодействия классов друг с другом для завершения работы. Слежение за выполнением программы может совершенно дезориентировать вас, если вы использовали процедурные языки, начинающиеся с начала и выполняющиеся до конца, но это лучше всего понять на практике.

    Как пакетируется Java-приложение, для того чтобы другие могли использовать его, или как передается код, который они могут использовать в своих собственных программах (например, библиотеки полезных объектов или интегрированную среду)? Создается Java Archive (JAR) — файл, в который спакетирован ваш код, для того чтобы другие программисты могли включить его в свой Java Build Path в Eclipse или в свой classpath при использовании инструментальных программ командной строки. Опять Eclipse значительно облегчает вашу работу. Создание JAR-файла в Eclipse (и во многих других IDE) является простой процедурой:

    1. В вашем рабочем пространстве нажмите правой кнопкой мыши на пакет intro.core и выберите Export .
    2. Выберите JAR file в диалоговом окне Export , затем нажмите Next .
    3. Перейдите в месторасположение, куда хотите поместить ваш JAR-файл, присвойте ему любое имя и расширение .jar.
    4. Нажмите Finish

    Вы должны увидеть ваш JAR-файл в указанном вами месте. Если имеется JAR-файл (ваш или из другого источника), вы можете использовать классы, находящиеся в нем, в вашем коде, если поместите его в ваш Java Build Path в Eclipse. Сделать это не трудно. У нас пока нет кода, который нужно добавить к нашему пути, но выполните следующие действия, которые нужно было бы для этого сделать:

    1. Нажмите правой кнопкой мыши на проекте Intro в вашем рабочем пространстве, затем выберите Properties .
    2. В диалоговом окне Properties выберите закладку Libraries.
    3. Здесь вы увидите кнопки для Add JARs. и Add External JARs. , которые вы можете использовать для помещения JAR-файлов в ваш Java Build Path.

    Если код (то есть файлы классов) в JAR-файлах находится в вашем Java Build Path, вы можете использовать эти классы в вашем Java-коде без получения ошибки компилятора. Если JAR-файл включает исходный код, вы можете связать эти исходные файлы с файлами классов в вашем пути. Тогда вы можете пользоваться всплывающей подсказкой и даже открыть и просмотреть код.

    Написание хорошего Java-кода

    Вы уже знаете достаточно много о синтаксисе Java, но это не совсем то, в чем заключается профессиональное программирование. Что делает Java-программы «хорошими»?

    Вероятно, существует столько ответов на этот вопрос, сколько имеется профессиональных Java-программистов. Но у меня есть несколько предложений, с которыми, я уверен, согласились бы большинство профессиональных Java-программистов, и которые улучшают качество Java-кода. По правде говоря, я являюсь сторонником agile-методов (динамичных методов), таких как Экстремальное Программирование (Extreme Programming — XP), поэтому многое в моих представлениях о «хорошем» коде сформировано agile-сообществом и, в частности, принципами XP. Тем не менее, я считаю, что большинство опытных профессиональных Java-программистов согласилось бы с советами, которые я дам в данном разделе.

    В данном руководстве мы создали простой класс Adult . Даже после того, как мы переместили метод main() в другой класс, Adult имел более 100 строк кода. Он имеет более 20 методов, и, в действительности, выполняет не много работы в сравнении со многими профессионально созданными классами, которые вы, вероятно, видите (и создаете). Это маленький класс. Нередко можно увидеть классы с числом методов от 50 до 100. Что делает их хуже классов, имеющих меньшее число методов? Наверное, ничего. Должно быть столько методов, сколько вам нужно. Если вам нужно несколько вспомогательных методов, выполняющих, в основном, одинаковую работу, но принимающих различные параметры (как наши методы addMoney() ), — это прекрасный вариант. Просто ограничивайте список методов только теми, которые действительно нужны, не более.

    Обычно класс с очень большим числом методов содержит нечто, ему не свойственное, поскольку такой гигантский объект делает слишком много. В своей книге «Рефакторинг» Мартин Фаулер (Martin Fowler) называет это «загрязнением кода чуждыми методами» (Foreign Method code smell). Если у вас есть объект со 100 методами, вы должны хорошо подумать, не является ли этот один объект в действительности комбинацией нескольких объектов. Большие классы обычно отстают в школе. То же самое касается и Java-кода.

    Маленькие методы также предпочтительны, как и маленькие классы, и по тем же причинам.

    Одним из огорчений, которые есть у опытных ОО-программистов в отношении языка Java, является то, что он дает широким массам пользователей объектно-ориентированный подход, но не учит их, как им правильно пользоваться. Другими словами, он дает достаточно веревки, чтобы повеситься (хотя и меньше, чем дает C++). Обычно это можно увидеть в классе с методом main() длиной в пять миль, или в одном методе под названием doIt() . То, что вы можете поместить весь ваш код в один метод вашего класса, не означает, что вы должны это делать. Язык Java имеет больше синтаксических излишеств, чем большинство других ОО-языков, поэтому некоторая многословность необходима, но не злоупотребляйте этим.

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

    Ограничивайте каждый метод до производительности одного действия.

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

    Ответ должен быть очевидным. По некоторым причинам программисты испытывают антипатию к длинным именам. Конечно, абсурдно длинное имя может быть неудобным, но достаточная для понимания длина имени обычно не является абсурдно большой. У меня нет проблем с таким именем метода, как aReallyLongMethodNameThatIsAbsolutelyClear() . Но если в три часа ночи, пытаясь понять, почему моя программа не работает, я встречаю метод с названием a() , то хочу кого-нибудь ударить.

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

    Метод isEmpty() объекта ArrayList полезен сам по себе, но это условие в нашем выражении if можно улучшить, применив метод Adult с названием hasMoney() , который выглядит следующим образом:

    Теперь наше выражение if больше похоже на английский:

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

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

    Почти во всех моих Java-проектах никто не боялся создавать классы, но мы также постоянно пытались уменьшить количество классов, не делая наши намерения менее ясными.

    Я когда-то писал обширные комментарии в моих программах. Вы могли читать их как книгу. Потом я стал немного умнее.

    Каждая программа обучения науке программирования, каждая книга по программированию и множество программистов, я уверен, советуют вам комментировать свой код. В некоторых случаях комментарии полезны. Во многих случаях они делают код более трудным для поддержки. Подумайте о том, что вы должны сделать при изменении кода. Есть в этом месте комментарий? Если есть, вам лучше бы менять комментарий, иначе он будет устаревшим и со временем может вовсе не описывать код. Исходя из моего опыта, это удваивает ваше время на обслуживание программы.

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

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

    Стиль кодирования на самом деле зависит от того, что необходимо и приемлемо в вашей среде. Я даже не знаю стиля, который мог бы назвать «типичным». Он часто зависит от личного вкуса. Например, вот некоторый фрагмент кода, который вызывает у меня судороги, пока я его не поменяю:

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

    Нет способа «правильного» или «неправильного». Один просто короче другого. Что же происходит, когда мне приходится кодировать вместе с тем, кто предпочитает первую форму? Мы говорим об этом, выбираем стиль кодирования, который собираемся придерживаться, затем фиксируем его. Единственным правилом на все случаи жизни является унификация. Если кто-то из работающих над проектом использует другой стиль, чтение кода станет трудным. Выберите стиль и не меняйте его.

    Некоторые Java-программисты любят выражения switch . Я думал, что они хороши, но потом понял, что выражение switch на самом деле является просто набором выражений if ; это обычно означает, что условная логика появляется в моем коде более чем в одном месте. Это дублирование кода, что недопустимо. Почему? Потому что присутствие одинакового кода в нескольких местах затрудняет его изменение. Если у меня есть один и тот же switch в трех местах, и нужно изменить один вариант, я должен поменять три фрагмента кода.

    Теперь, можете ли вы выполнить рефакторинг кода таким образом, чтобы имелось только одно выражение switch ? Отлично! Я не имею ничего против его использования. В некоторых ситуациях выражение switch более понятно, чем вложенные if . Но если вы видите, что оно появляется в нескольких местах — это проблема, которую вы должны решить. Простой способ предотвратить ее появление — избегать выражения switch до тех пор, пока оно не будет лучшим средством выполнения работы. Мой опыт говорит, что это случается редко.

    Я оставил самые сомнительные рекомендации напоследок. Вдохните глубже.

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

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

    Такого рода разочарование часто наступает при использовании чужого кода. Вы можете увидеть метод, делающий точно то, что вам нужно, но он не доступен. Иногда есть веские причины этого, поэтому имеет смысл ограничить доступность. Однако иногда единственной причиной того, что метод не указан как public , является то, что парни, написавшие код, думали: «Никому и никогда даже не понадобиться обратиться к нему». А может они думали: «Никто не должен обратиться к нему, потому что…», вовсе не имея серьезной на это причины. Очень часто люди используют ключевое слово private только потому, что оно существует. Не поступайте так.

    Указывайте методы как public , а переменные как protected , если не имеете серьезной причины для ограничения доступа.

    Теперь вы знаете, как создавать хороший Java-код и как поддерживать его хорошим.

    Лучшей книгой по этой теме является «Рефакторинг» Мартина Фаулера (Martin Fowler). Ее даже читать легко. Рефакторинг означает изменение дизайна существующего кода без изменения его результатов. Фаулер говорит о «загрязнениях кода» («code smells»), которые требуют рефакторинга, и очень подробно рассматривает различные технические приемы для их исправления. По моему мнению рефакторинг и способность писать код в стиле test-first (сначала тестирование) является самым важным умением, которое должны освоить начинающие программисты. Если бы каждый программист был хорош в обоих этих навыках, то это революционизировало бы отрасль. Если вы отлично освоите их, будет легче получить работу, поскольку вы будете способны достичь лучших результатов, чем большинство из ваших соратников.

    Писать Java-код относительно не сложно. Писать хороший Java-код — это мастерство. Стремитесь стать мастером.

    Резюме

    В данном руководстве вы познакомились с ООП, изучили синтаксис языка Java, позволяющий создавать полезные объекты, и попробовали поработать с IDE, помогающей управлять вашей средой разработки. Вы научились создавать объекты, которые могут делать много полезной работы, хотя определенно не все, что вы можете себе представить. Но вы можете продолжить свое обучение несколькими способами, включая внимательное изучение Java API и исследование других возможностей языка Java при помощи других руководств developerWorks. Ссылки на них приведены в разделе «Ресурсы».

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

    Вопросы по Java на собеседовании (1)

    1. Принципы объектно-ориентированного программирования (ООП)
    2. Class и его свойства
    3. Методы базового суперкласса Object
    4. Отношения между классами : ассоциация, агрегация и композиция
    5. Конструкторы класса
    6. Абстрактный класс
    7. Статический класс и его свойства
    8. Модификаторы свойств класса
    9. Использование this и super
    10. Сигнатура метода
    11. Переопределение и перегрузка методов
    12. Инициализация статических полей
    13. Использование оператора instanceof
    14. Использование модификатора final
    15. Порядок инициализации статических полей потомка и его предка
    16. Определения понятия «интерфейса»
    17. Вложенные и внутренние классы
    18. Аннотации классов
    19. Использование метода finalize
    20. Отличие final, finally, finalize

    1. Принципы объектно-ориентированного программирования (ООП)

    Объе́ктно-ориенти́рованное программи́рование (ООП) — это методология программирования, основанная на представлении программного обеспечения в виде совокупности объектов, каждый из которых является экземпляром определенного класса. Базовой основой любого класса является Object, включающий определенный набор методов.

    Основные принципы ООП : абстракция, инкапсуляция, наследование, полиморфизм.

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

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

    Инкапсуляция (encapsulation) — это свойство объединения данных и методов в одном классе, позволяющее отделить внутреннее представление от внешнего (интерфейса). Инкапсуляция позволяет закрыть доступ к полям и методам класса другим объектам, либо предоставить доступ к полям класса через свои методы. Можно сказать, что, с точки зрения java, инкапсуляция – это «сокрытие реализации».

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

    Наследование — это свойство, позволяющее одному классу получить все или отдельные свойства другого класса. Класс, от которого производится наследование, называется базовым, родительским или суперклассом. Новый класс, наследующий свойства базового, является потомком, наследником, дочерним или производным классом.

    Полиморфизм (polymorphism) — это свойство позволяет использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта. Полиморфные объекты наследуют один и тот же базовый класс; не обязательно, что базовый класс является родителем, он может «быть предком в третьем колене».

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

    Подробное описание и примеры ООП представлены здесь.

    2. Class и его свойства

    Класс (Class) – это шаблон описания одного или нескольких объектов. Объект представляет экземпляр класса. Шаблон (класс) включает свойства, определяемые характеристиками объектов (полями объекта) и методами их управления. Поля класса определяют, например, такие характеристики объекта, как вес, размер, цвет, площадь и т.д. Методы класса позволяют «оперировать» его полями – определять значение (методы set), выдавать значение (методы get) и т.д.

    Class может наследовать свойства другого класса. Первоосновой любого класса является суперкласс Object. Пример класса :

    В примере представлен класс прямоугольника Rectangle, наследующий свойства класса (фигуры) Shape, и включающий переопределенные методы draw базового класса Shape и toString суперкласса Object. Метод toString возвращает описанные в Shape свойства класса width и height в текстовом виде. При описании свойств класса был использован модификатор public.

    Более подробное описание класса с примерами представлено здесь.

    3. Методы суперкласса Object

    Object является базовым суперклассом для всех остальных объектов/классов Java, т.е. каждый класс наследует свойства Object. Соответственно все классы наследуют следующие методы суперкласса Object :

    public final native Class getClass(); возвращает в run-time класс данного объекта;
    public native int hashCode(); возвращает hash-код;
    public boolean equals(Object obj); сравнивает текущий клас с объектом obj;
    protected native Object clone() throws CloneNotSupportedException; клонирование объекта;
    public String toString(); возвращает строковое представление объекта;
    public final native void notify(); возобновление работа потока, находящегося в ожидании освобождения «монитора» данного объекта;
    public final native void notifyAll(); возобновление работы всех потоков, находящихся в ожидании освобождения «монитора» данного объекта;
    public final native void wait(long timeout) throws InterruptedException; поток переходит в режим ожидания в течение указанного времени timeout;
    public final void wait(long timeout, int nanos) throws InterruptedException; переход потока в режим ожидания в течение указанного времени timeout;
    public final void wait() throws InterruptedException; перевод потока в ожидание, пока другой поток не вызовет notify() или notifyAll() методы для этого объекта;
    protected void finalize() throws Throwable; вызывается сборщиком мусора, когда garbage collector определил, что ссылок на объект больше нет.

    Подробное описание с примерами использования методов hashCode и equals представлено в разделе безопасности. Примеры использования методов многопочного программирования wait, notify, notifyAll c описанием класса Thread (поток) и интерфейса Runnable можно увидеть здесь. Метод finalize описан ниже.

    4. Отношения между классами : ассоциация, агрегация и композиция

    Ассоциация — это отношение, при котором объекты одного типа определенным образом связаны с объектами другого типа. Так объект одного типа может содержать или использовать объект другого типа. Например, игрок Player играет в определенной команде Team. В этом случае класс Player будет связан отношением ассоциации с классом Team. Таким образом, идея ассоциации достаточно простая — два объекта могут быть между собой связаны и это надо как-либо образом описать.

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

    Агрегация определяет отношение одного объекта к другому. Так, например, студент может посещать дополнительные факультативные занятия.

    Композиция определяет более «жесткое отношение», при котором один объект может быть только частью другого объекта. Например Машина и Двигатель : двигатель может существовать отдельно без машины, но он не может быть в двух или трех машинах одновременно, в отличии от студента, который может посещать различные факультативные занятия.

    5. Конструкторы класса

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

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

    6. Абстрактный класс

    Класс может быть объявлен абстрактным при помощи ключевого словом ‘abstract’. Абстрактный класс не предполагает создания экземпляров, а может быть использован только как базовый класс. Таким образом, абстрактные классы реализуют на практике один из принципов ООП — полиморфизм. Абстрактный класс может как содержать, так и не содержать абстрактные методы. Абстрактный метод базового класса должен быть переопределен для его неабстрактных потомков; в базовом классе абстрактный метод только описывается.

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

    7. Статический класс и его свойства

    Класс или его свойства могут быть объявлены статическими при помощи ключевого словом ‘static’. При обращении к статическим свойствам класса необходимо в префиксе указывать наименование класса. Статический класс может обращаться к нестатическим членам класса только при помощи объекта реализации класса.

    В java можно использовать статический импорт, применяемый для импорта статических членов класса или интерфейса. Так, например, для импорта статических методов Math.pow() и Math.sqrt() можно использовать в секции import следующий код :

    Статический импорт позволяет использовать вызов методов без наименования класса в префиксе.

    8. Модификаторы свойств класса

    Модификаторы класса позволяют определить уровень доступа к свойству класса. В java существуют следующие модификаторы доступа :

    public (открытый) : поле и метод доступны всем;
    protected (защищённый) : поле и метод доступны всем классам пакета и наследникам;
    private (закрытый) : поле и метод доступны только методам этого класса;
    без модификатора : default, friendly, доступ по умолчанию только внутри своего собственного пакета.

    Примечание : конструктор класса также может иметь модификатор. Если класс имеет единственный конструктор с модификатором private, то невозможно создать объект данного класса. От такого класса нельзя наследоваться. При попытке наследования будет выдаваться ошибка :
    There is no default constructor available in nameClass
    А при попытке создать объект этого класса:
    nameClass() has private access in nameClass

    Можно ли обойти отмеченное выше Примечание? Можно, если в этом классе создать метод, который возвращает экземляр данного класса. Пример :

    А теперь, создаем объект класса, у которого единственный конструктор с модификатором private. Конечно, new TestPrivate() здесь не пройдет, но решить данную задачу с использованием внутреннего статического метода можно.

    9. Использование this и super

    Чтобы обратиться к свойству текущего класса используют this, а к свойству базового класса — super. Так, например, в следующем примере класс Dog наследует свойства класса Animal и переопределяет метод eat(). Для обращения к переопределенному методу eat() своего класса используется вызов this.eat() в методе thisEat. Но, чтобы обратиться из наследника Dog к методу eat() базового класса Animal используется вызов super.eat() в методе superEat.

    Более подробное описание наследования и пример использования this и super представлено здесь.

    10. Сигнатура метода

    Сигнатура метода (method signature) включает наименование метода с параметрами. При этом порядок параметров методов имеет значение. В сигнатуру метода не входят модификаторы, возвращаемое значение и вызываемые методом исключения. Также в сигнатуры не включены операнды synchronized, native и аннотация метода.

    11. Переопределение и перегрузка методов

    Если в иерархии классов сигнатура метода класса-наследника совпадает с сигнатурой метода родительского класса, то метод подкласса переопределяет метод базового класса. Вызов переопределённого метода из своего подкласса всегда ссылается на версию, определённую подклассом, а версия метода родительского класса будет скрыта. Чтобы вызвать «переопределенный» метод родительского класса следует использовать super.

    В одном java-классе можно создавать несколько методов с одинаковыми наименованиями, но разными сигнатурами. Создание метода с тем же именем, но с другим набором параметров называется перегрузкой. На основе фактических параметров JVM определяет какой из перегруженных методов класса должен выполняться при вызове.

    Статические методы могут быть перегружены нестатическими. При вызове из другого класса статического метода используется наименование класса, при вызове нестатического метода – объект реализации.

    12. Инициализация статических полей

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

    Динамический блок является дополнением к конструктору. В следующем коде роль динамического блока играет процедура init :

    Статические блоки в java выполняются до выполнения конструктора. С их помощью инициализируются статические поля.

    13. Использование оператора instanceof

    Оператор instanceof позволяет проверить принадлежность объекта к определенному классу/родителю. Выражение возвращает true, если объект является экземпляром класса или его потомком. В следующем примере демонстрируется использование оператора instanceof в различных условиях :

    14. Использование модификатора final

    Модификатор final может быть применен к полям, методам или классам. Смысл в его применении зависит от сущности, к которой он применен :

    1. Класс с модификатором final не может иметь наследников.
    2. Метод с модификатором final не может быть переопределен в классах наследниках.
    3. Поле помеченное при помощи слова final не может изменить свое значение после инициализации. Инициализируется поле либо при описании, либо в конструкторе, либо в статическом или динамическом блоке.
    4. Значение локальных переменных, а также параметров метода помеченных при помощи слова final не могут быть изменены после присвоения.

    15. Порядок инициализации статических полей потомка и его предка

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

    16. Определения понятия «интерфейса»

    Ключевое слово «интерфейс» (interface) используется для описания полностью абстрактного класса. В описании интерфейса определяются статические поля и методы без тела (кода). Описание методов интерфейса выполняется в классе, реализующим данный интерфейс.

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

    Пример описания интерфейса SomeInterface и его реализации в классе SomeClass :

    По умолчанию все поля, описанные в интерфейсе автоматически являются статическими (static) и неизменными (final). Все методы и переменные неявно объявляются как public. Начиная с 8-ой версии Java в интерфейсе можно объявлять static методы, но они должны включать тело метода.

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

    Описание и пример использования интерфейса представлено здесь.

    17. Вложенные и внутренние классы

    Вложенный класс (nested classes) представляет собой класс, который объявлен внутри объявления другого класса. Вложенные классы могут быть статическими и нестатическими. Нестатические вложенные классы имеют и другое название — внутренние классы (inner classes).

    Внутренние Java классы делятся на три вида :

    • внутренние классы-члены;
    • локальные классы;
    • анонимные классы.

    Внутренние классы-члены (member inner classes) ассоциируются не с самим внешним классом, а с его экземпляром. Такие классы имеют доступ ко всем полям и методам внешнего класса.

    Локальные классы (local classes) определяются в блоке java кода. На практике чаще всего объявление происходит в методе некоторого другого класса. Хотя объявлять локальный класс можно внутри статических и нестатических блоков инициализации.

    Анонимный класс (anonymous class) — это локальный класс без имени.

    Из внутреннего нестатического класса можно обратиться к нестатическому полю внешнего класса с использованием наименования внешнего класса и оператора this. Например, OuterClass.this.fieldName.

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

    Описание и пример использования вложенных (внутренних) классов представлено здесь.

    18. Аннотации классов

    Аннотация («annotation») в языке Java – это специальная форма метаданных, которая может быть добавлена в исходный код. Аннотированы могут быть пакеты, классы, методы, переменные и параметры. Аннотации стали доступны в самом языке начиная с 5-ой версии Java. В 6-ой версии Java аннотации были интегрированы в компилятор javac.

    Имеются встроенные широко используемые аннотации, которые отслеживаются средой разработки IDE и применяются к методу класса :

    • @Override — проверка переопределения метода. IDE вызывает предупреждение компиляции, если метод не найден в родительском классе;
    • @Deprecated — IDE отмечает, что метод устарел и вызывает предупреждение компиляции, если метод используется.
    • @SuppressWarnings — аннотация указывает IDE подавить предупреждения компиляции.

    Аннотации, применяемые к другим аннотациям :

    • @Retention — определяет режим хранения аннотации (в исходном коде или в скомпилированном классе);
    • @Documented — отмечает аннотацию для включения в документацию;
    • @Target — отмечает аннотацию как ограничивающую (какие элементы java-аннотации могут быть к ней применены);
    • @Inherited — отмечает, что аннотация может быть расширена подклассами аннотируемого класса.

    Подробнее об аннотациях можно прочитать здесь.

    19. Использование метода finalize

    Метод finalize предназначен для автоматического освобождения системных ресурсов, занимаемых объектом. Это может быть удобным, чтобы постоянно не помнить, что, например, необходимо закрыть соединение с каким-либо ресурсом.

    Можно использовать finalize для чистки данных. Но, во-первых, нет гарантии, что он будет вызван, если где-то в коде осталась ссылка на объект. Ну, и во-вторых, нет гарантии на то, что метод будет вызван сразу. Это связано с тем, что если в объекте переопределен метод finalize, то он вызывается не сразу, а помещается в очередь, которая обрабатывается специально созданным для этого потоком. Следует отметить, что в очередь на «финализацию» попадают только те объекты, в которых переопределен метод finalize.

    Порядок очистки объектов

    Cборщик мусора Garbage Collector не вызывает методы finalize() напрямую (по крайней мере, в HotSpot 1.6), а только добавляет соответствующие объекты в специальный список, вызывая статический метод java.lang.ref.Finalizer.register(Object). Объект класса Finalizer формирует двусвязный список ссылок на объекты, для которых необходимо вызвать finalize(). Т.е. в списке хранятся ссылки на следующий и предыдущий finalize().

    Непосредственный вызов методов finalize() происходит в отдельном потоке «Finalizer» (java.lang.ref.Finalizer.FinalizerThread), который создаётся при запуске виртуальной машины, а точнее в статической секции при загрузке класса Finalizer. Методы finalize() вызываются последовательно в том порядке, в котором были добавлены в список сборщиком мусора. Соответственно, если какой-то finalize() зависнет, то он подвесит поток «Finalizer», но не сборщик мусора. Таким образом, если объект не имеет метода finalize(), то он будут исправно удаляться, а вот объекты с методом finalize будут увеличивать очередь до тех пор, пока «не отвиснет» поток «Finalizer», не завершится приложение или не кончится память.

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

    20. Отличие final, finally, finalize

    У этих операторов общим является только корень final, и то, что они являются зарезервированными словами в Java.

    final — модификатор, применяющийся к классам, методам, переменным.

    finally является частью конструкции try-catch-finally, где играет роль блока, который выполняется независимо от событий происходящих в try-catch и выполняется в любом случае.

    Занятие 1


    Знакомство с оболочкой Eclipse

    Назначение, особенности и преимущества Eclipse

    Eclipse — это расширяемая IDE (интегрированная среда разработки). IDE — удобно организованный набор инструментов, необходимых для работы над программным проектом.

    Eclipse — универсальная платформа, которая может использоваться для разработки приложений на любом языке программирования (например, можно использовать язык Python после установки подключения Pydev (http://sourceforge.net/projects/pydev/), но изначально «родным» для Eclipse является Java (на которой, кстати, сам Eclipse и написан).

    Наиболее важными особенностями Eclipse являются:

    1. Кроссплатформенность. Eclipse выполняется на всех распространенных платформах: Windows, Linux и MacOS X. Еще важнее то, что его функции одинаковы на каждой из этих платформ.
    2. Универсальность и расширяемость. В Eclipse реализована возможность использова­ния различных инструментов, разработанных сторонними программистами.
    3. Открытость и бесплатность. Eclipse является OpenSource-проектом (т.е. его исходные коды доступны любому желающему и кто угодно может присоединиться к разработке этого инструмента). Eclipse имеет активное сообщество, постоянно работающее над улучшением программы и расширением ее возможностей.

    Рабочая среда Eclipse

    Первое, что вы видите при запуске Eclipse – диалоговое окно, позволяющее выбрать место, где будет располагаться рабочее пространство. Рабочее пространство – каталог, в ко­тором будет сохраняться ваша работа.

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

    Основными составляющими рабочей среды являются представления (views), редакто­ры (editors) и проекции или перспективы (perspectives).

    Представление – это небольшой раздел внутри рабочей среды, который служит для навигации по неко­торой категории объектов (такой, как ресурсы или пакеты), открытия редакторов, отображения свойств активных редакторов. Например, представ­ление Navigator показывает проекты и дру­гие ресурсы, а представление Bookmarks отображает все закладки в Workbench вме­сте с именами файлов, с которыми эти за­кладки связаны. На рисунке изображен пра­вый верхний угол ра­бочей среды с ак­тивным представление Outline.

    Все измене­ния, сде­ланные в представлениях, немедлен­но сохраняют­ся.

    Другой тип визуальных компонентов Workbench – редакторы, которые используются для просмотра и редактирования некоторого ре­сурса (например, программного кода). При выборе ресурса появляется подходящий редактор. Например, откройте любой текстовый до­кумент (с расширением .txt) командой File Open File. и вы увидите встроенный редактор простого неформатируемого текста. Если что-либо набрать в этом редакторе, на его вкладке, где написано название файла, появится звездочка. Она означает, что редактор содержит не сохраненные изменения. Они сохранятся, если нажать Ctrl + S или выбрать команду File Save .

    Существует множество полезных представлений, которые добавляются в окно рабочей среды командой Window Show View . Однако вместо того, чтобы добавлять их по одному, удобнее бывает переключать проекцию (perspective). Проекция (или перспектива) – это набор представлений и редакторов, специально подобранный для выполнения некоторой задачи. После запуска в Eclipse открывается перспектива Java, настроенная собственно на написание программы. Для отладки программы часто используется проекция Debug. Переключить проекцию можно командой Window Open Perspective . На­звание текущей проекции отображается в правом верхнем углу рабочей среды (см. рисунок).

    Первая программа на Java

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

    Для создания проекта выполните команду File New Project . В появившемся окне выберите Java Project и нажмите «Далее». Укажите имя своего проекта. Обратите внимание, что в директории, указанной вами как рабочее пространство, будет создана папка с именем вашего проекта (если, конечно, не изменить настройки в этом окне, чего для первого раза мы делать не будем). Нажмите кнопку «Готово».

    Теперь в представлении PackageExplorer в левой части рабочей среды присутствует ваш проект. В любой момент его можно удалить, щелкнув по его названию правой кнопкой мыши и выбрав Delete . После этого Eclipse спросит, уничтожить ли заодно папку с файлами проекта (при необходимости можно и уничтожить).

    Если вы не удалили проект, к нему можно добавить файлы и папки с помощью команд контекстного меню New File и New Folder соответственно. Если проект большой, то ему необходима структура вложенных папок. Но в случае Java-проекта все несколько иначе. Дело в том, что фрагменты Java-программы сгруппированы в пакеты, а для каждого пакета создается отдельная папка. Пакет создается командой New Package . Для пакета тоже надо придумать имя. В результате в папке проекта будет создана новая папка с этим именем. Можете проверить.

    Просматривать ресурсы проекта может быть удобнее с помощью представления Navigator. Откройте его командой Window Show View . Вы увидите, что кроме директо­рий проекта и пакета Eclipse создал два вспомогательных файла .classpath и .project. Они лег­ко откроются в редакторе, но особого интереса для нас они сейчас не представляют.

    Программа на Java всегда состоит из одного или нескольких классов. Создать класс можно командой New Class в контекстном меню представления Navigator (или Package Explorer, не имеет значения). При создании класса необходимо выбрать пакет, к которому он будет относиться (выберите только что созданный вами пакет) и придумать ему имя. Имена классов принято начинать с прописной буквы. Если не соблюсти это правило хорошего тона, Eclipse выдаст предупреждение, но ничего страшного не произойдет.

    Для наших целей полезно поставить галочку в разделе «Какие методы вы хотите со­здать в своем классе?» напротив опции public static void main(String[] args) . В результате в теле класса будет сгенерирован метод (функция) main() . Java требует, чтобы хотя бы в одном из классов программы существовал метод с таким заголовком. Именно он и будет выполнен при старте программы.

    В результате наших действий в папке пакета будет создан файл с именем нашего класса и расширением .java. Eclipse откроет редактор кода, в котором отобразится содержимое этого файла. Оно будет примерно следующим (имена пакета и класса, конечно, могут отличаться):

    Команды, составляющие тело функции, можно написать вместо автоматически сгене­рированного комментария // TODO Auto-generated method stub . Мы напишем только одну команду, которая будет выводить на экран классическую строку «Hello, world!»:

    System.out.println( «Hello, world!» );

    Осталось программу запустить. Для этого выполним команду Run Run и получим диалоговое окно с нетривиальными настройками запуска. В левой части этого окна надо вы­брать Java Application (приложение Java). Немного подумав, Eclipse найдет наш класс, содер­жащий метод main() и предложит начать запуск программы именно с него (в правой части окна на вкладке Main должны появиться названия нашего проекта и нашего класса). Помимо этого вниманию программиста предлагается еще несколько закладок. Например, на второй из них – Arguments – предлагается ввести параметры командной строки (если программа рас­считана на вызов из командной строки с параметрами). Для нашей простой программы ниче­го дополнительно указывать не нужно. Просто нажмите кнопку Run .

    В результате работы программы осуществляется вывод данных в так называемую консоль. В операционной системе MS DOS консолью служил весь экран монитора. Eclipse же открывает нам представление Console, в котором (если все сделано правильно) и отобразится строка «Hello, world!» — результат вывода нашей программы.

    Теперь для повторного запуска программы (например, если мы решили внести в нее ка­кие-то изменения или надо показать преподавателю), можно пойти более легким путем — выполнить команду Run Run Last Launched (еще раз запустить предыдущее приложение) или просто нажать Ctrl + F11 .

    Основы синтаксиса языка Java

    Определения

    Понятия программы и алгоритма (повторение)

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

    Назначение любой компьютерной программы — преобразование входных данных в вы­ходные данные. Алгоритм программы определяет способ преобразования входных данных в выходные.

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

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

    Приступая к написанию программы НЕОБХОДИМО СРАЗУ ПОНЯТЬ:

    1. Для чего вообще нужна эта программа (что она делает, в общих чертах)?
    2. Какие у этой программы входные данные (и откуда они берутся)?
    3. Какие у этой программы выходные данные (и куда их отправить)?
    4. Каким образом входные данные должны быть преобразованы в выходные (алгоритм)? Это самая сложная часть раздумий программиста, но пока нет ответа на три предыдущих вопроса, приступать к ней не имеет смысла.

    При написании простой программы необходимо:

    1. Получить входные данные.
    2. Реализовать алгоритм превращения входных данных в выходные.
    3. Выдать результат работы программы (выходные данные): вывести на экран, передать по сети и т.п.

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

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

    Литература по теме:

    1. Школьный учебник информатики.

    Основные конструкции алгоритма (повторение)

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

    Итак, алгоритм — это последовательность действий по преобразованию входных дан­ных в выходные.

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

    В словесной форме.

    Пусть, например, у нас есть задача: найти максимум из двух чисел. Из условия следует, что входными данными будут являться два числа (причем, не указано, откуда они берутся, поэтому пользователь может ввести их, например, с клавиатуры), а выходными данными — одно число, представляющее собой максимальное из двух введенных. Тогда словесным опи­санием алгоритма будет следующее: «Попросить пользователя ввести два числа. Получить эти числа с клавиатуры. Если первое число больше второго, вывести его на экран, в против­ном случае вывести на экран второе число».

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

    Входные и выходные данные изображаются в виде параллелограмма. Вычислительные (и некоторые другие действия) в виде прямоугольников. Для указания проверки условий ис­пользуются ромбы, а стрелки изображают переход от одного действия к другому. Алгоритм рассматриваемой выше задачи в виде блок-схемы будет изображен так, как показано на рисунке:

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

    Отдельные шаги алгоритма (независимо от того, каким образом он записан) связывают­ся друг с другом с помощью трех стандартных конструкций, которые реализованы абсолют­но во всех языках программирования:

    Последовательное выполнение. Шаги выполняются друг за другом.

    Ветвление. В зависимости от выполнения некоторого условия (в рассмотренном при­мере это x > y ? ) выполняется та или иная ветвь программы.

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

    Рассмотрим задачу: вывести на экран все четные числа меньше 10. Для этой задачи можно использовать алгоритм, основанный на последовательном выполнении шагов и алго­ритм, использующий цикл. Диаграммы для обоих вариантов представлены на рисунке:

    Первая диаграмма выглядит понятнее, но в случае, когда вывести надо не 5 чисел, а 100, диаграмма (и программа, соответствующая этому алгоритму) увеличится в 20 раз, а в программе, соответствующей второму алгоритму, изменится только одно место: 10 поменяется на 100. Именно поэтому повторяющиеся действия оформляют в виде циклов, хотя во многих случаях без них можно и обойтись.

    Запомните: алгоритм должен строиться только из трех названных конструкций!

    Литература по теме:

    1. Школьный учебник информатики.

    Основы основ синтаксиса Java

    1. Язык Java различает прописные и строчные буквы. Это означает, что имена всех функций и ключевые слова следует записывать в точности так, как они значатся в примерах и справочниках.
    2. Каждая команда (оператор) в языке Java должна заканчиваться точкой с запятой.
    3. Программа на Java состоит из одного или нескольких классов. Абсолютно вся функциональная часть программы (т.е. то, что она делает) должна быть помещена в методы тех или иных классов. (Класс и метод, как понятия объектно-ориентированного программирования, будут рассматриваться в третьем занятии. Там же будет рассмотрен синтаксис классов. В первых упражнениях используйте классы, которые по умолчанию генерирует Eclipse.)
    4. Классы группируются в пакеты.
    5. Хотя бы в одном из классов должен существовать метод main() , в точности такой, как в рассмотренном нами примере. (На первых порах разбираться или пытаться запомнить правильное написание этого метода необязательно – Eclipse все сгенерирует сам, если поста­вить нужную галочку.) Именно этот метод и будет выполняться первым.

    В простейшем случае про­грамма может состоять из одного (или даже ни одного) пакета, одного класса внутри пакета и единственного мето­да main() внутри класса. Команды программы будут записываться между строчкой

    public static void main(String[] args) <

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

    Комментарии

    Комментарии — это поясняющие надписи, которые используют программисты для улучшения понятности кода. При компиляции программы комментарии игнорируются, поэтому в них может быть написано все, что угодно. Главное показать, что данная надпись является коммен­тарием и ее не надо пытаться трактовать как команды программы. В Java это делается одним из следующих образов:

    1. Ставятся две косые черты // . С этого момента и до конца строки можно писать все, что угодно — Java будет считать это комментарием.
    2. В начале комментария ставятся символы /* , а в конце — */ . В этом случае комментарий может занимать какое угодно количество строк.
    3. Особо выделяются комментарии для документирования, которые помещаются меж­ду маркерами /** и */ . Об их использовании будет рассказано позже.

    Правила записи литералов

    Целые числа (целочисленные литералы) в Java можно записывать обычным образом в де­сятичной форме: 12345, +4, -11.

    Кроме этого, можно записывать целые числа в восьмеричной форме, на­чиная с нуля (0777, -056) и в шестнадцатеричной форме, начиная с нуля и латинской буквы x (0xFFFF, 0x14, 0xA1BC).

    Действительные литералы записываются в десятичной системе счисления, целая часть отделяется от дробной точкой.

    Действительное число можно записать в форме с плавающей точкой, например: 5.4e19, 17E-11, -123e+4. Та часть числа, которая стоит до буквы e называется мантиссой, а часть, ко­торая стоит после буквы e – порядком. Запись означает следующее: надо возвести 10 в сте­пень порядка и умножить на мантиссу. Иногда действительно удобнее записать 1e-9, чем 0.000000001.

    Одиночные символы записываются в апострофах, например, ‘a’ , ‘D’ , ‘@’ .

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

    Управляющая последовательность Описание
    \ddd Восьмеричный символ (ddd)
    \uxxxx Шестнадцатиричный символ Unicode (xxxx)
    \’ Апостроф
    Кавычка
    \\ Обратная косая черта
    \r Возврат каретки (carriage return)
    \n Перевод строки (line feed, new line)
    \t Горизонтальная табуляция (tab)
    \b Возврат на символ (backspace)

    Управляющая последовательность также заключается в апострофы.

    В первой строке таблицы говорится, что любой символ можно задать с помощью его кода (с десятичной кодировкой от 0 до 255), записав этот код в восьмеричной системе счисления. Например, буква «ж» в кодировке CP1251 запишется управляющей последовательностью ‘\346’

    При необходимости можно указать код любого символа в кодировке Unicode – после обратной черты и латинской буквы u – четырьмя шестнадцатеричными символами. Например, ‘\u0055’ – это буква U.

    Строки символов записываются в кавычках. Открывающая и закрывающая ка­вычка должны находиться в одной строке программного кода.

    Для строк определена операция сцепления +, которая позволяет собрать несколько строк в одну («приписывая» их друг к другу).

    Если строковая константа слишком длинная и плохо воспринимается в программном коде при записи ее в одну строчку, можно записать ее в несколько строчек, соединяя их с помощью операции сцепления строк. Например:

    «Это очень длинная строковая константа, записанная» + «на двух строках исходного текста»

    Управляющие символы и коды записыва­ются внутри строки точно также с обратной чертой (но без апострофов).

    Логические литералы — это true (истина) и false (ложь).

    Идентификаторы

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

    Идентификатор может состоять из букв, цифр, знака подчеркивания _ и знака доллара $ (последний использовать не рекомендуется, Java пользуется им для своих нужд). Идентификатор не может начинаться с цифры. В качестве идентификаторов не могут использоваться ключе­вые слова Java (а также литералы true, false и null ).

    Как было отмечено выше, язык Java различает простые и строчные буквы. Это значит, что myAge , myage и MyAge – имена совершенно разных объектов. Будьте внимательны: ошибка в регистре — весьма распространенный случай!

    При выборе имен рекомендуется придерживается следующих правил хорошего стиля

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

    Имена методов и переменных начинаются со строчных (маленьких букв); если в имени содержится несколько слов, то каждое следующее слово начинается с заглавной буквы. Например, myVar , x , y , newBigCounter .

    Имена констант записываются полностью прописными буквами; если имя содержит несколь­ко слов, между ними ставится знак подчеркивания. Например, PI , COUNT_OF_MONTHS.

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

    Типы данных

    Для хранения целых чисел в Java чаще всего используется тип int .

    Вообще в языке Java существует четыре целочисленных типа: byte , short , int , long . Они различаются объемом памяти, которая будет выделена под переменную и, соответственно, диапазоном значений, которые можно в этой переменной хранить. Чаще всего используемый тип int занимает в памяти 4 байта и пригоден для хранения чисел от -2147483648 до 2147483647. Тип byte расходует меньше всего памяти и подходит для работы с небольшими числами (от -128 до 127). Типы short и long занимают 2 и 8 байт соответственно.

    Для действительных чисел подходит тип double .

    Действительные (вещественные) числа (или числа с плавающей точкой) представлены двумя типами: float и double . Тип float занимает 4 байта памяти и не дает большой степени точности при работе с очень большими или очень маленькими числами. Его рекомендуют использовать в случае, когда дробная часть нужна, но высокая точность не требуется (например, для измерения расстояний в метрах, но с учетом сантиметров и миллиметров или измерения цен в рублях с учетом копеек). При необходимости более точных вычислений рекомендуется оперировать с величинами типа double (например, такая переменная может хранить величину синуса угла).

    Действительные литералы, такие как 5.3 , 8.0 , 2e-3 , Java считает относящимися к типу double . Если они должны использоваться в программе как величины типа float , необходимо заканчивать их на букву f : 5.3f , 8.0f , 2e-3f .

    Для хранения одиночных символов используется тип char . Java считает его разновидностью целочисленных типов (поскольку каждый символ задается своим кодом в кодировке Unicode), так что к char применимы все операции с целыми числами.

    Логические величины (принимающие истинное либо ложное значение) представлены типом boolean .

    Таким образом, в Java определено восемь простых типов, особенности которых представлены в таблице:

    Тип Размер (бит) Минимальное значение Максимальное значение Описание Значение по умолчанию
    boolean логический тип false
    char 16 Unicode 0 Unicode 2 16 -1 символьный тип ‘\u0000’
    byte 8 -128 +127 целое со знаком
    short 16 -2 15 +2 15 -1 целое со знаком
    int 32 -2 31 +2 31 -1 целое со знаком
    long 64 -2 63 +2 63 -1 целое со знаком 0L
    float 32 3.4е-038 3.4е+038 вещественное 0.0f
    double 64 1.7е-308 1.7е+308 вещественное 0.0d

    Объявление переменных

    В языке Java (как и во многих других языках) переменную требуется описать перед ее использованием. Описать переменную – значит дать ей имя и определить ее тип.

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

    Примеры объявления переменных:

    int x; // Объявление целочисленной переменной x double a, b; // Объявление двух вещественных переменных a и b char letter = ‘ Z ‘; // Объявление символьной переменной letter, инициализация начальным значением ‘Z’ boolean b1 = true , b2, b3 = false ; // Объявление трех логических переменных, первая из них будет иметь значение true, последняя — false

    Ocновные операции языка

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

    Математические операции

    Операция Использование Описание
    + op1 + op2 Складывает op1 и op2
    op1 — op2 Вычитает op1 из op2
    * op1 * op2 Умножает op1 на op2
    / op1 / op2 Делит op1 на op2
    % op1 % op2 Вычисляет остаток от деления op1 на op2

    Операции сравнения, результатом является значение логического типа: true (истина) или false (ложь)

    Операция Использование Возвращает истину(true), если
    > op1 > op2 op1 больше чем op2
    >= op1 >= op2 op1 больше или равен op2
    op1 op1 меньше op2
    op1 op1 меньше или равно op2
    == op1 == op2 op1 и op2 равны
    != op1 != op2 op1 и op2 не равны

    Логические операции

    Операция Использование Возвращает истину(true), если
    && op1 && op2 op1 и op2 оба истины (конъюнкция)
    || op1 || op2 один из op1 или op2 истинен (дизъюкция)
    ! !op op — ложь (отрицание)
    ^ op1 ^ op2 op1 и op2 различны (исключающее или)

    Операции && и || отличаются тем, что не обязательно вычисляют значение второго операнда. Например, && вычисляет значение первого операнда и, если оно ложно, сразу возвращает false , а || возвращает true сразу, если видит, что первый операнд – истина. В Java есть аналогичные по действию операции & и | , они вычисляют значения обоих операндов, прежде чем произвести над ними операцию.

    Операции сдвига

    (работают с битовым представлением первого операнда)

    Операция Использование Описание
    >> op1 >> op2 сдвигает биты op1 вправо на op2
    op1 сдвигает биты op1 влево на op2
    >>> op1 >>> op2 сдвигает биты op1 вправо на op2 (без учёта знака)

    Битовые операции

    (работают с битовым представлением операндов)

    op2

    Операция Использование Описание
    & op1 & op2 побитовое и
    | op1 | op2 побитовое или
    ^ op1 ^ op2 побитовое исключающее или
    побитовое дополнение

    Операция ?:

    Операция ?: тернарная, то есть имеет три операнда. Первый операнд — условие, выражение логического типа. Второй и третий операнды — выражения любого другого типа. Операция работает следующим образом: если условие равно true , она возвращает в качестве результата свой второй операнд, а если false , то третий.

    Например, выражение (5 > 3)? 7+1: 2*2 будет иметь значение 8, а выражение (5 == 3)? 7+1: 2*2 — значение 4. Эта запись выглядит не очень наглядно, но программисты часто используют ее для сокращения своего кода. Так, вместо последовательности команд:

    if (x > 0) y = 45 + a*2; // оператор if рассматривается ниже else y = 45 — b*3;

    y = 45 + ((x > 0)? a*2: -b*3);

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

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

    Значение связывается с переменной с помощью оператора присваивания. В языке Java он записывается простым знаком равенства:

    Слева от оператора присваивания всегда указывается переменная. Выражение справа должно соответствовать переменной по типу. Оно может представлять собой просто литерал (например, число или символ):

    x = 7; // переменной x присваивается значение 7 letter = ‘Q’ ; // переменной letter присваивается значение ‘Q’

    В общем случае выражение — это то, что может быть вычислено (например, результат математической операции или результат, возвращаемый некоторым методом):

    a = 7.5 + 2.4; // переменной a присваивается 9.9 как результат вычислений

    В выражении наряду с литералами могут участвовать другие переменные. Вместо них подставляется их текущее значение. В результате выполнения команды:

    переменная b примет значение 10.9.

    Итак, оператор присваивания действует следующим образом. Сначала вычисляется зна­чение выражения в правой части, а затем полученный результат присваивается переменной, указанной в левой части. Возможна даже следующая ситуация:

    Эта команда увеличивает текущее значение целочисленной переменной x на 4.

    А следующие команды записаны неправильно и работать не будут:

    5 = x + 7; // слева должна стоять переменная x + 3 = 14; // слева должна стоять просто одна переменная x = 4.5; // переменная x может принимать только целочисленные значения

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

    Когда переменной одного типа присваивается величина другого типа, происходит используется приведение (преобразование) типов. Для числовых типов ( byte , short , int , long , float , double , char ) оно происходит автоматически, если тип изменяемой переменной может «вместить» значение другого типа.

    Например, если переменной типа int присвоить значение типа byte , автоматически произойдет преобразование типа byte в тип int . Аналогично тип float может быть приведен к типу double и т.п.

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

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

    long j = ( long )1.0; //используем оператор приведения типа к long, j = 1 char ch = ( char )1001; //используем оператор приведения типа к char, ch = ‘d’ byte b2 = ( byte )(100); //используем оператор приведения типа от int к byte, b2 = 100 byte b3 = ( byte )(100 * 2); //внимание! происходит деление по модулю, b3 = -56

    Ошибка несовпадения типов часто возникает применительно к действительным литералам. Например, нельзя выполнить присваивание a = 7.5 + 2.4; , если переменная a имеет тип float , поскольку литералы 7.5 и 2.4 считаются относящимся к типу double . Чтобы не было ошибки, необходимо использовать приведение типов:

    или указать, что литералы также относятся к типу float:

    a = 7.5f + 2.4f; // это тоже правильная команда

    Практически для каждой бинарной операции существует своя разновид­ность оператора присваивания. Например, для операции сложения + существует унарный оператор присваивания += , который увеличивает значение операнда на заданную величину:

    x += 8; // то же самое, что x = x + 8 (x увеличивается на 8)

    Аналогично для других операций: операторы *= , -= , /= , %= , &= ^= и т.д:

    x *= 3; // то же самое, что x = x * 3 (x увеличивается в 3 раза) b1 ^= b2; // то же самое, что b1 = b1 ^ b2

    Упражнение 1

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

    Подсказка: вы можете воспользоваться уже созданным в Eclipse проектом, вставив нужные команды после команды вывода строки «Hello, world!» либо вместо нее.

    Операторы инкремента и декремента

    Операторы инкремента и декремента ++ и –– увеличивают и уменьшают на единицу значение операнда. Гораздо удобнее использовать команду x++; вместо команды x = x+1;

    Операторы инкремента и декремента тоже возвращают значение. Это значит, что пра­вомерно выполнить команду

    В результате переменная x увеличится на 1, а переменная y примет значение, в семь раз большее старого значения x. Можно также выполнить и такую команду:

    В результате переменная x увеличится на 1, а переменная y примет значение, в семь раз большее нового значения x.

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

    Простейшая форма записи условного оператора имеет вид:

    if (условие) команда

    Условие в скобках представляет собой логическое выражение, т.е. может быть истин­ным или ложным. Если условие окажется истинным, команда будет выполнена, в противном случае ничего не произойдет. Например:

    if (x // если значение переменной x меньше 17, x присвоить 17

    Если же необходимо, чтобы в случае, когда условие ложно, была выполнена какая-то другая команда, используют расширенную форму оператора if:

    if (условие) команда1 else команда2

    В примере, рассмотренном выше, мы можем захотеть присвоить переменной x значе­ние 5, если условие x не выполняется (зачем оно нам, другой вопрос).

    Если необходимо использовать несколько взаимоисключающих условий, их можно за­писать следующим образом:

    if (условие1) команда1 else if (условие2) команда2 else if (условие3) команда3 . else командаN

    Упражнение 2

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

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

    Составные команды

    Несколько команд языка Java можно объединить в одну составную команду, используя фигурные скобки <>. Например, можно записать:

    Составные команды можно использовать везде, где и обычные. Например, в операторе if , если при выполнении условия надо выполнить несколько действий:

    if (x x = 17; letter = ‘S’ ; > else

    Конструкция из фигурных скобок называется также блоком команд, а фигурные скобки — границами блока.

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

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

    Часто выбор команды, которую необходимо выполнить, зависит от значения некоторой переменной (или выражения). Например, пользователю предлагается ввести знак операции и в зависимости от введенного символа требуется вывести на экран результат сложения, вычи­тания и т.п. или, если введен неправильные знак, сообщение об ошибке. В этом случае удоб­но использовать оператор выбора switch , имеющий следующую форму записи:

    Значение1, значение2 и т.д. — это константы или выражения, в которых участвуют только константы. Выражение в скобках после ключевого слова switch может содержать переменные. Это выражение вычисляется, а затем ищется соответствие результата с одним из значений после ключевого слова case . Если такое соответствие найдено, то выполняется вся последовательность команд, расположенная между двоеточием и ближайшей командой break . Если не найдено ни одного соответствия, выполнится последовательность команд по умолчанию, стоящая после ключевого слова default . Например:

    char oper; // Знак операции, его выберет пользователь . // Будем считать, что к этому моменту пользователь выбрал знак switch (oper)

    Можно опустить раздел default . В этом случае если совпадение не будет найдено, не выполнится ни одна команда.

    Оператор цикла while

    Цикл while имеет следующую форму:

    while (условие) команда

    Если условие в скобках (представляющее собой логическое выражение типа boolean ) истинно, будет выполнена команда — тело цикла (это может быть простая команда или по­следовательность команд в фигурных скобках), после чего программа снова вернется к вы­полнению этого оператора и будет повторять это до тех пор, пока условие не окажется ложным.

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

    К примеру, следующий фрагмент программы выводит четные числа от 2 до 10:

    int x = 2; while (x System.out.println(x); x += 2; >

    Существует другой вариант записи цикла while :

    do команда while (условие)

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

    Упражнение 3

    С помощью цикла while выведите все нечетные числа от 1 до 10.

    Подсказка: немного измените алгоритм вывода четных чисел.

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

    Цикл for обычно используется, когда известно заранее сколько раз должно повториться выполнение команды (или последовательности команд). Он имеет следующую форму:

    for (команда инициализации; условие; команда перехода) тело_цикла

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

    Обычно цикл for используется в следующем виде:

    for ( int i = 1; i тело_цикла;

    В этом примере тело_цикла выполнится ровно 10 раз. При этом на каждой итерации будет доступна переменная i (она называется переменной цикла), последовательно пробегаю­щая значения от 1 до 10. Следующий фрагмент программы выводит четные числа от 2 до 10 (аналогично примеру цикла while):

    for ( int i = 1; i

    Упражнение 4

    С помощью цикла for выведите все нечетные числа от 1 до 10.

    Операторы break и continue

    Когда тело цикла ( for или while ) состоит из нескольких команд, может возникнуть ситуация, что на очередной итерации выполнять их все нет необходимости. В этом случае полезными оказываются операторы break и continue .

    Оператор break прекращает выполнение текущего цикла, независиом от того, выполняется ли условие его окончания.

    Оператор continue прекращает выполнение текущей итерации цикла. То есть, если в теле цикла встречается этот оператор, то остальные, следующие за ним команды пропускаются и начинается новая итерация (повторение) цикла.

    Заключение

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

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

    1. Вязовик Н.А. Программирование на Java. (главы 1 — 4, 7, 10)

    2. Хабибуллин И.Ш. Самоучитель Java 2. (глава 1)

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

    Уроки по основам языка программирования JAVA для начинающих

    Уроки по основам языка java

    Основы java для начинающих

    Курс JAVA для начинающих рассчитан на новичков в программировании. Наши уроки по java с самого начала дадут вам представление о языке программирования java, его основных принципах и возможностях. После прохождения основ Java вы сможете уверенно осваивать уроки по разработке мобильных приложений на андроид. Уроки обновляются и дополняются. Желаем удачи на пути программиста!

    Список уроков по Java

    Справочник по языку программирования JAVA

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

    Справочник по языку программирования java. Материал взят из открытых источников.

    Уроки по андроид-программированию:

    Продвинутые курсы разработки приложений для андроид:

    Продвинутые курсы по созданию приложений и игр для андроид помогут вам за очень короткий срок создать реальное работающее android-приложение или игру, внедрить в него рекламные баннеры и загрузить в маркет Google Play.

    Язык программирования Java: с чего начать изучение. Где применяется Java

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

    Основы программирования на языке Java

    Java как язык с поддержкой объектного ориентирования отвечает основным принципам ООП:

    В центре «Джава», как и в других ООЯ, — объект и класс с конструкторами и свойствами. Начинать обучение языку программирования Java лучше не с официальных ресурсов, а с пособий для новичков. В таких манулах подробно описываются возможности, предоставляются примеры кода. В книгах наподобие «Язык программирования Java для начинающих” подробно разъясняются основные принципы и особенности названного языка.

    Особенности

    Код на языке программирования Java транслируется в байт-код, затем выполняется на виртуальной машине JVM. Преобразование в байт-код осуществляется на Javac, Jikes, Espresso, GCJ. Существуют такие компиляторы, которые транслируют язык «Си» в Java байт-код. Таким образом, приложение на «Си» может работать на любых платформах.

    Синтаксис «Джава» характеризуется следующим:

    1. Имена классов должны начинаться с большой буквы. Если название состоит из нескольких слов, то второе должно начинаться с верхнего регистра.
    2. Если для формирования метода используется несколько слов, то второе из них должно начинаться с большой буквы.
    3. Обработка начинается с метода main() — он является частью каждой программы.

    Язык программирования Java имеет 8 примитивных типов. Они представлены ниже.

    • Boolean — логический тип, принимает всего два значения true и false.
    • Byte — наименьший целочисленный тип размером 1 байт. Он используются при работе с потоком данных или файлов, необработанными двоичными данными. Имеет диапазон от -128 до 127.
    • Short имеет диапазон от -32768 до 32767, используется для представления чисел. Размер переменных этого типа — 2 байта.
    • Int тоже обозначает числа, но его размер — 4 байта. Он чаще остальных используется для работы с целочисленными данными, а byte и short иногда повышаются до int.
    • Long используются для больших целых чисел. Возможные значения находятся в диапазоне от -9223372036854775808 до 9223372036854775807.
    • Float и double применяются для обозначения дробных. Их разница в том, что float удобен, когда не требуется высокая точность в дробной части числа.
    • Double выводит на экран все знаки после разделителя «.», а float — только первые.
    • String наиболее используемый примитивный тип, с помощью которого задаются строки.

    Классы и объекты

    Важную роль в книге «Изучение языка программирования Java для начинающих» занимают классы и объекты.

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

    В «Джава» можно создавать подкласс, который будет наследовать методы родительского. Для этого используется слово extends:

    • class имя_класса extends имя_суперкласса <>;

    Конструктор является составляющим любого класса, даже если это не задано явно. В таком случае компилятор его создает самостоятельно:

    • public class Class < public Class()< >public Class(String name)< >>

    Имя конструктора совпадает с именем класса, по умолчанию у него есть всего один параметр:

    Object создается из класса с помощью оператора new():

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

    Point р = new Point()

    public static void main(String args[]) <

    Point p1 = new Point();

    Point p2 = new Point();

    Объектные переменные и объекты — совершенно разные сущности. Object variables являются ссылками. Они могут указывать на любые переменные непримитивного типа. В отличие от C++ их типовое преобразование жестко регламентировано.

    Поля и методы

    Поля — это все переменные, связанные с классом или объектом. По умолчанию они являются локальными и не могут использовать в других классах. Для доступа к полям используется оператор «.»:

    Можно задать статические поля с помощью ключевого слова static. Такие поля являются единственным способом хранить глобальные переменные. Это связано с тем, что в «Джава» попросту нет global variables.

    Реализована возможность импорта переменных для получения доступа из других пакетов:

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

    void init(int a, int b) <

    В примере выше класс Point имеет поля типа integer x и y, метод init(). Доступ к методам, как и к переменным, осуществляется путем использования оператора «.»:

    Свойство init ничего не возвращает, поэтому имеет тип void.

    Переменные

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

    Одновременно может быть объявлено несколько переменных. Для их перечисления используется запятая:

    Инициализации осуществляется после или во время объявления:

    int a = 10, b = 10;

    Существует несколько типов:

    • local variables (локальные);
    • instance variables (переменные экземпляра);
    • static variables (статические).

    Local variables объявляют в методах и конструкторах, они создаются во время запуска последних и уничтожаются после завершения. Для них запрещено указывать access modifiers и управлять уровнем доступности. Они не видимы за пределами объявленного блока. В Java переменные не имеют начального значения, поэтому оно в обязательном порядке присваивается перед первым использованием.

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

    Static variables называются переменными класса. Их имена начинаются с символа в верхнем регистре, конкретизируются модификатором static. Они используются как константы, соответственно, к ним прибавляется один спецификатор из списка:

    Запускаются в начале программы, уничтожаются после остановки выполнения. Так же, как переменные экземпляра, имеют стандартные значения, которые присваиваются пустым переменным. У чисел — значение 0, булевые переменные имеют значение false, ссылки на объект изначально имеют null. Статические переменные вызываются в следующем виде:

    Сборщик мусора

    В самоучителе «Язык программирования Java для новичков» раздел автоматического сборщика мусора является наиболее интересным.

    В Java, в отличие от языка «Си», невозможно ручное удаление объекта из памяти. Для этого реализован метод автоматического удаления — сборщик мусора. При традиционном удалении через null происходит лишь устранение ссылки на объект, а сам объект удаляется. Существуют методы принудительной сборки мусора, хотя они не рекомендованы для использования в обычной работе.

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

    Модификаторы

    Различают разные типы модификаторов. Кроме тех, которые определяют способ доступа, существует модификаторы методов, переменных, класса. Методы, объявленные как private, доступны только в объявленном классе. Такие переменные не могут использоваться в других классах и функциях. Public открывает доступ для любого класса. Если нужно получить Public class из другого пакета, то его следует предварительно импортировать.

    Модификатор protected похож по действую на public — открывает доступ к полям класса. В обоих случаях переменные могут использоваться в других классах. Но паблик-модификатор доступен абсолютно для всех, а протектед-модификатор — только для наследуемых классов.

    Модификатор, который применяется при создании методов, — static. Это означает, что созданный метод существует независимо от экземпляров класса. Модификатор Final не управляет доступом, а указывает на невозможность дальнейшего манипулирования значениями объекта. Он запрещает изменение того элемента, для которого указан.

    Final для полей делает невозможным изменение первого значения переменной:

    public static void mthod(String[] args) <

    final int Name = 1;

    int Name = 2;// выдаст ошибку

    Переменные с модификатором final являются константами. Их принято писать только заглавными буквами. CamelStyle и другие способы не работают.

    Final для методов указывает запрет на изменение метода в наследуемом классе:

    final void myMethod() <

    Final для классов означает, что нельзя создать наследников класса:

    final public class Class <

    Abstract — модификатор создания абстрактных классов. Любой абстрактный класс и абстрактные методы предназначены для дальнейшего расширения в других классах и блоках. Модификатор transient указывает виртуальной машине не обрабатывать заданную переменную. В этом случае та просто не сохранится. Например, transient int Name = 100 не сохранится, а int b сохранится.

    Платформы и версии

    Существующие семейства языка программирования Java:

    • Standard Edition.
    • Enterprise Edition.
    • Micro Edition.
    • Card.
    1. SE — является основным, широко используется для создания пользовательских приложений для индивидуального использования.
    2. EE — набор спецификаций для разработки ПО уровня предприятия. Содержит больше возможностей, чем SE, поэтому используется в коммерческих масштабах на крупных и средних предприятиях.
    3. ME — предназначены для устройств с ограниченной мощностью и памятью, у них, как правило, малый размер дисплея. Такими устройствами являются смартфоны и КПК, ресиверы цифрового телевидения.
    4. Card — предназначена для устройств с крайне ограниченными вычислительными ресурсами, например таких, как смарт-карты, sim-карты, банкоматы. Для этих целей был изменен байт-код, требования к платформе, составляющее библиотек.

    Применение

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

    Активно используется для создания мобильных приложений под Android. Программа компилируется в нестандартный байт-код, выполняется на виртуальной машине ART. Для компиляции применяется Android Studio. Это IDE от компании «Гугл» является официальной для разработки под ОС Android.

    Microsoft разработала собственную реализацию виртуальной машины Java MSJVM. Она имела такие отличия, которые ломали основополагающую концепцию кроссплатформенности — отсутствовала поддержка некоторых технологий и методов, имелись нестандартные расширения, работающие только на платформе Windows. Microsoft выпустил язык J#, синтаксис и работа в целом которого очень напоминает Java. Он не соответствовал официальной спецификации и в итоге был исключен из стандартного инструментария разработчика Microsoft Visual Studio.

    Язык программирования Java и среда

    Разработка программного обеспечения осуществляется в таких IDE:

    1. JDK.
    2. NetBeans IDE.
    3. Eclipse IDE.
    4. IntelliJ IDEA.
    5. JDeveloper.
    6. Java для iOS.
    7. Geany.

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

    Удобно писать код на языке программирования Java в среде Netbeans и Eclipse IDE. Это свободные интегрированные среды для разработки, они подходят под все платформы «Джава». Также используются для программирования на Python, PHP, JavaScript, C++.

    IntelliJ IDE от компании Jetbrains распространяется в двух вариантах: бесплатном и коммерческом. Поддерживает написание кода на многих языках программирования, существуют сторонние плагины от разработчиков, в которых реализовано еще большее количество ЯП.

    JDeveloper — еще одна разработка от компании Oracle. Полностью написана на Java, поэтому работает на всех операционных системах.

    Цукерберг рекомендует:  Практические советы по улучшению качества кода
    Понравилась статья? Поделиться с друзьями:
    Все языки программирования для начинающих