Кен Арнольд Джеймс Гослинг

Вид материалаДокументы

Содержание


Глава 5ЛЕКСЕМЫ, ОПЕРАТОРЫ И ВЫРАЖЕНИЯ
5.1. Набор символов
Лексемами (tokens)
Подобный материал:
1   ...   21   22   23   24   25   26   27   28   ...   81

Глава 5
ЛЕКСЕМЫ, ОПЕРАТОРЫ И ВЫРАЖЕНИЯ


В этом нет ничего особенного.
Все, что от вас требуется, —
это нажимать нужные клавиши в нужный момент,
а инструмент будет играть сам.

Иоганн Себастьян Бах

В этой главе рассматриваются основные “строительные блоки” Java —типы, операторы и выражения. Мы уже видели довольно много Java-программ и познакомились с их компонентами. В этой главе приводится детальное описание базовых элементов.

5.1. Набор символов


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

В отличие от них, программы на языке Java написаны в Unicode — 16-разрядном наборе символов. Первые 256 символов Unicode представляют собой набор Latin-1, а основная часть первых 128 символов Latin-1 соответствует 7-разрядному набору символов ASCII. В настоящее время окружение Java может читать стандартные файлы в кодировке ASCII или Latin-1, немедленно преобразуя их в Unicode. /В Java используется Unicode 1.1.5 с исправленными ошибками. Справочная информация приведена в разделе "Библиография"/

В настоящее время лишь немногие текстовые редакторы способны работать с символами Unicode, поэтому Java распознает escape-последовательности вида \udddd, которыми кодируются символы Unicode; каждому d соответствует шестнадцатеричная цифра (ASCII-символы 0–9, а также a–f или A–F для представления десятичных значений 10–15). Такие последовательности допускаются в любом месте программы — не только в символах и строковых константах, но также и в идентификаторах. В начале последовательности может стоять несколько u; записывается и как \u0b87, и как \uu0b87.   следовательно, символ /Использование "множественных u" может показаться странной, но на то есть веские причины. При переводе Unicode-файла в формат ASCII, приходится кодировать символы Unicode, лежащие за пределами ASCII-диапазона, в виде escape-последовательностей. Таким образом, представляется в виде \u0b87. При обратном переводе осуществляется обратная замена; но что произойдет, если исходный текст в содержал \u0b87? В этом случае при обратной   кодировке Unicode вместо символа замене исходный текст изменится (синтаксический анализатор не заметит никаких изменений - но не читатель программы!) Выход заключается в том, чтобы при прямом переводе вставлять дополнительные u в уже существующие \udddd, а при обратном - убирать их, и, если u не останется, заменять escape-последовательность эквивалентным символом Unicode./

5.2. Комментарии


Комментарии в Java бывают трех видов:

// комментарий - игнорируются символы от // до конца строки

/* комментарий */ - игнорируются символы между /* и следующим */, включая

завершающие символы строк \r, \n и \r\n.

/** комментарий */ - игнорируются символы между /** и следующим */, включая

перечисленные выше завершающие символы. Документирующие

комментарии должны располагаться непосредственно после

объявления класса, члена класса или конструктора; они

включаются в автоматически генерируемую документацию.

Когда мы говорим “символы”, то имеем в виде любые символы Unicode. Комментарии в Java могут включать произвольные символы Unicode: “инь-янь” (\u262f), восклицание (\u203d) или “снеговика” (\u2603).

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

/* Закомментируем до лучших времен; пока не реализовано


/* Сделать что-нибудь этакое */

universe.neatStuff();


*/

Первая комбинация символов /* начинает комментарий; ближайшая парная */ заканчивает его, оставляя весь последующий код синтаксическому анализатору, который сообщает об оставшихся символах */ как о синтаксической ошибке. Лучший способ временно убрать фрагмент из программы — либо поместить // в начале каждой строки, либо вставить конструкцию if (false):

if (false) {

// Вызвать метод, когда он будет работать

dwim();

}

Разумеется, данный фрагмент предполагает, что метод dwim определен где-то в другом месте программы.

5.3. Лексемы


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

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

return 0;

нельзя убрать пробел между return и 0, поскольку это приведет к появлению неправильного оператора

return0;

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

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

j = i+++++i; // НЕВЕРНО

неверно интерпретируется как

j = i++ ++ +i; // НЕВЕРНО

вместо правильного

j = i++ + ++i;