Глава 3. Лексическая структура
Содержание
В данной главе описывается лексическая структура языка программирования Java.
Программы записываются в Юникоде (§3.1), но предоставляются лексические преобразования (§3.2), чтобы можно было включать любые символы Юникода, используя только символы ASCII с помощью экранирования Юникода (§3.3). Определены разделители строк (§3.4), чтобы поддерживать различные соглашения существующих систем, сохраняя при этом последовательные номера строк.
Символы Юникода, полученные в результате лексических преобразований, сводятся к последовательности элементов входных данных (§3.5), являющихся пробелами (§3.6), комментариями (§3.7) и токенами. Токены — это идентификаторы (§3.8), ключевые слова (§3.9), литералы (§3.10), разделители (§3.11) и операторы (§3.12) синтаксической грамматики.
Программы пишутся с использованием набора символов Юникод (§1.7). Информация об этом наборе символов и его связанных кодировках может быть найдена на сайте https://www.unicode.org/.
Java SE Platform отслеживает Стандарт Юникод по мере его развития. Точная версия Юникода, используемая конкретным выпуском, указана в документации класса Character.
Стандарт Юникод изначально разрабатывался как кодировка символов с фиксированной шириной 16 бит. Позднее он был изменен, чтобы позволить символы, чье представление требует более 16 бит. Диапазон допустимых кодовых точек теперь U+0000 до U+10FFFF, используя обозначение шестнадцатеричного числа U+n. Символы, чьи кодовые точки больше U+FFFF, называются дополнительными символами. Для представления всего диапазона символов с использованием только 16-битовых единиц Стандарт Юникод определяет кодировку UTF-16. В этой кодировке дополнительные символы представлены парами 16-битовых кодовых единиц, первая из которых из диапазона высоких суррогатов (U+D800 до U+DBFF), а вторая из диапазона низких суррогатов (U+DC00 до U+DFFF). Для символов в диапазоне U+0000 до U+FFFF значения кодовых точек и кодовых единиц UTF-16 совпадают.
Язык программирования Java представляет текст в последовательностях 16-битовых кодовых единиц, используя кодировку UTF-16.
Некоторые API платформы Java SE, в основном в классе Character, используют 32-битовые целые числа для представления кодовых точек как отдельных сущностей. Платформа Java SE предоставляет методы для преобразования между 16-битными и 32-битными представлениями.
В данном спецификации используются термины кодовая точка и кодовая единица UTF-16, где представление важно, и общий термин символ, где представление не имеет отношения к обсуждению.
За исключением комментариев (§3.7), идентификаторов (§3.8) и содержимого символьных литералов, строковых литералов и текстовых блоков (§3.10.4, §3.10.5, §3.10.6), все элементы входных данных (§3.5) в программе формируются только из символов ASCII (или экранированных символов Юникода (§3.3), которые приводят к символам ASCII).
ASCII (ANSI X3.4) — это американский стандартный код для обмена информацией. Первые 128 символов кодировки Unicode UTF-16 — это символы ASCII.
Поток символов Юникода преобразуется в последовательность токенов с помощью следующих трех шагов лексического преобразования, которые применяются поочередно:
-
Преобразование экранированных символов Юникода (§3.3) в исходном потоке символов Юникода в соответствующий символ Юникода. Экранирование Юникода вида
\uxxxx, гдеxxxx— шестнадцатеричное значение, представляет кодовую единицу UTF-16, чье кодирование —xxxx. Этот шаг преобразования позволяет выразить любую программу, используя только символы ASCII. -
Преобразование потока Юникода, полученного на шаге 1, в поток входных символов и разделителей строк (§3.4).
-
Преобразование потока входных символов и разделителей строк, полученного на шаге 2, в последовательность элементов входных данных (§3.5), которые после удаления пробелов (§3.6) и комментариев (§3.7), составляют токены, которые являются терминальными символами синтаксической грамматики (§2.3).
На каждом шаге используется самое длинное возможное преобразование, даже если результат в конечном итоге не образует правильную программу, в то время как другое лексическое преобразование было бы правильным. Есть два исключения для учета ситуаций, которые требуют более подробного преобразования: на шаге 1 для обработки непрерывных \ символов (§3.3) и на шаге 3 для обработки контекстных ключевых слов и смежных > символов (§3.5).
Входные символы a--b токенизируются как a, -- и b, что не является частью какой-либо грамматически корректной программы, хотя токенизация a, -, -, b может быть частью грамматически корректной программы. Токенизация a, -, -, b может быть реализована с входными символами a- -b (с символом ASCII SP между двумя - символами).
Можно предположить, что исходный ввод \\u1234 преобразуется в символ \ и (следуя правилу «наибольшей длины») в экранирование Юникода вида \u1234. На самом деле, ведущий символ \ заставляет этот исходный ввод преобразовать в семь отдельных символов: \ \ u 1 2 3 4.
Компилятор языка программирования Java ("компилятор Java") сначала распознаёт экранирования Юникода в своём исходном коде, преобразуя ASCII-символы \u, за которыми следуют четыре шестнадцатеричных цифры, в символ исходного кода, обозначающий единицу кодировки UTF-16 (§3.1) для указанного шестнадцатеричного значения. Одно экранирование Юникода может представлять символы в диапазоне U+0000 до U+FFFF; для представления дополнительных символов в диапазоне U+010000 до U+10FFFF требуется два последовательных экранирования Юникода. Все другие символы в исходном коде компилятора распознаются как символы исходного кода и передаются без изменений.
Этот этап преобразования приводит к последовательности символов ввода Юникода, все из которых являются символами исходного кода (любые экранирования Юникода были преобразованы в символы исходного кода).
u {u} 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F \, u и шестнадцатеричные цифры здесь — все ASCII-символы.
Производство СимволВводаЮникода неоднозначно, потому что ASCII-символ \ в исходном коде компилятора может быть преобразован либо в СимволИсходногоКода, либо в \ ЭкранированияЮникода (за которым следует ASCII-символ u). Чтобы избежать неоднозначности, при обработке каждого ASCII-символа \ в исходном коде компилятора необходимо учитывать последние символы исходного кода, полученные на данном этапе преобразования:
-
Если последний символ исходного кода в результате был сам преобразован из экранирования Юникода в исходном коде компилятора, то ASCII-символ
\может начинать экранирование Юникода.Например, если последний символ исходного кода в результате был обратной косой чертой, возникшей из экранирования Юникода
\u005cв исходном коде, то следующий ASCII-символ\в исходном коде может начинать ещё одно экранирование Юникода. -
В противном случае, посчитайте, сколько обратных косых черт подряд появились как символы исходного кода в результате, начиная от символа, отличного от обратной косой черты или от начала результата. (Не имеет значения, возникла ли такая обратная косая черта из ASCII-символа
\в исходном коде компилятора или из экранирования Юникода\u005cв исходном коде компилятора). Если это число чётное, то ASCII-символ\может начинать экранирование Юникода; если нечётное, то ASCII-символ\не может начинать экранирование Юникода.Например, исходный код
"\\u2122=\u2122"приводит к одиннадцати символам" \ \ u 2 1 2 2 = ™ ", так как, хотя второй ASCII-символ\в исходном коде не может начинать экранирование Юникода, третий ASCII-символ\может, а\u2122является кодировкой Юникода для символа™.
Если допустимый \ не следует за u, то он обрабатывается как СимволИсходногоКода и остаётся частью потока экранированного Юникода.
Если допустимый \ следует за u, или если за ним следует более одной u, и последняя u не следует за четырьмя шестнадцатеричными цифрами, то возникает ошибка времени компиляции.
Символ, полученный с помощью экранирования Юникода, не участвует в дальнейших экранированиях Юникода.
Например, исходный код \u005cu005a приводит к шести символам \ u 0 0 5 a, потому что 005c — это значение Юникода для обратной косой черты. Он не приводит к символу Z, который имеет значение Юникода 005a, потому что обратная косая черта, полученная в результате обработки экранирования Юникода \u005c, не интерпретируется как начало дальнейшего экранирования Юникода.
Обратите внимание, что \u005cu005a не может быть записан в строковой литерале для обозначения шести символов \ u 0 0 5 a. Это связано с тем, что первые два символа, полученные в результате преобразования, \ и u, интерпретируются в строковой литерале как недопустимая последовательность экранирования (§3.10.7).
К счастью, правило о последовательных символах обратной косой черты помогает программистам создавать исходные коды, обозначающие экранирования Юникода в строковой литерале. Для обозначения шести символов \ u
0 0 5 a в строковой литерале просто необходимо добавить ещё \ рядом с существующим \, например, "\\u005a is Z". Это работает, потому что вторая \ в исходном коде \\u005a не может начинать экранирование Юникода, поэтому первая \ и вторая \ сохраняются как символы исходного кода, как и следующие пять символов u 0 0 5 a. Две \ интерпретируются в строковой литерале как последовательность экранирования для обратной косой черты, что приводит к строке с желаемыми шестью символами \ u 0 0 5 a. Без правила исходный код \\u005a обрабатывался бы как символ исходного кода \, за которым следует экранирование Юникода \u005a, которое становится символом исходного кода Z; это было бы бесполезно, потому что \Z является недопустимой последовательностью экранирования в строковой литерале. (Обратите внимание, что правило преобразует \u005c\u005c в \\, потому что преобразование первого экранирования Юникода в символ исходного кода \ не препятствует преобразованию второго экранирования Юникода в другой символ исходного кода \.)
Это правило также позволяет программистам создавать исходные коды, обозначающие последовательности экранирования в строковой литерале. Например, исходный код \\\u006e приводит к трём символам \ \ n, потому что первая \ и вторая \ сохраняются как символы исходного кода, а третья \ может начинать экранирование Юникода, и поэтому \u006e преобразуется в символ исходного кода n. Три символа \ \ n интерпретируются в строковой литерале как \
n, что обозначает последовательность экранирования для перевода строки. (Обратите внимание, что \\\u006e может быть записано как \u005c\u005c\u006e, потому что каждое экранирование Юникода \u005c преобразуется в символ исходного кода \, поэтому оставшийся исходный код \u006e предшествует чётному числу обратных косых черт и обрабатывается как экранирование Юникода для n.)
Язык программирования Java определяет стандартный способ преобразования программы, написанной на языке Юникод, в ASCII, который преобразует программу в форму, которую могут обработать инструменты, основанные на ASCII. Преобразование включает в себя преобразование всех экранирований Юникода в исходном тексте программы в ASCII путём добавления дополнительной u — например, \uxxxx становится \uuxxxx — и одновременного преобразования символов в исходном тексте, не являющихся ASCII, в экранирования Юникода, содержащие по одному u.
Эта преобразованная версия так же приемлема для компилятора Java и представляет точно такую же программу. Точный исходный текст Юникода может быть восстановлен из этой ASCII-формы путём преобразования каждой последовательности экранирования, где присутствует несколько u, в последовательность символов Юникода с одной u меньше, и одновременного преобразования каждой последовательности экранирования с одной u в соответствующий единственный символ Юникода.
Компилятор Java должен использовать обозначение \uxxxx в качестве формата вывода для отображения символов Юникода, когда подходящий шрифт недоступен.
Компилятор Java затем разделяет последовательность символов ввода Юникод на строки, распознавая разделители строк.
символ ASCII CR, также известный как "возврат"
символ ASCII CR, за которым следует символ ASCII LF
Строки завершаются символами ASCII CR, или LF, или CR LF. Два символа CR, непосредственно за которыми следует LF, считаются одним разделителем строк, а не двумя.
Разделитель строк указывает на завершение формы комментария // (§3.7).
Строки, определяемые разделителями строк, могут определять номера строк, создаваемые компилятором Java.
Результат — последовательность разделителей строк и символов ввода, которые являются терминальными символами для третьего шага процесса токенизации.
Символы ввода и разделители строк, которые получаются после обработки символов Юникод (§3.3) и затем распознавания строк (§3.4), сводятся к последовательности элементов ввода.
Те элементы ввода, которые не являются пробелами или комментариями, являются токенами. Токены — терминальные символы синтаксической грамматики (§2.3).
Пробелы (§3.6) и комментарии (§3.7) могут служить для разделения токенов, которые, если будут рядом, могли бы быть токенизированы другим способом.
Например, символы ввода - и = могут образовывать операторный токен -= (§3.12) только в том случае, если между ними нет пробелов или комментариев. В качестве другого примера, десять символов ввода staticvoid образуют один токен идентификатора, в то время как одиннадцать символов ввода static void (с символом ASCII SP между c и v) образуют пару токенов ключевых слов, static и void, разделенных пробелами.
В качестве особой уступки для совместимости с некоторыми операционными системами символ ASCII SUB (\u001a, или управляющий символ Z) игнорируется, если он является последним символом в потоке экранированного ввода.
Производство Вход является неоднозначным, что означает, что для некоторых последовательностей символов ввода существует более одного способа уменьшения символов ввода до элементов ввода (то есть, токенизировать символы ввода). Неопределенности разрешаются следующим образом:
-
Последовательность символов ввода, которые могут быть сведены либо к токену идентификатора, либо к токену литерала, всегда сводится к токену литерала.
-
Последовательность символов ввода, которые могут быть сведены либо к токену идентификатора, либо к токену зарезервированного ключевого слова (§3.9), всегда сводится к токену зарезервированного ключевого слова.
-
Последовательность символов ввода, которые могут быть сведены либо к контекстному ключевому слову, либо к другим (не ключевым) токенам, уменьшается в соответствии с контекстом, как указано в §3.9.
-
Если символ ввода
>появляется в контексте типа (§4.11), то есть как часть Типа или UnannType в синтаксической грамматике (§4.1, §8.3), то он всегда сводится к оператору численного сравнения>, даже когда он может быть объединён с соседним символом>для образования другого оператора.Без этого правила для символов
>, два последовательных>скобки в типе, таком какList<List<String>>, были бы токенизированы как оператор сдвига вправо со знаком>>, в то время как три последовательных>скобки в типе, таком какList<List<List<String>>>, были бы токенизированы как оператор сдвига вправо без знака>>>. Хуже того, токенизация четырёх или более последовательных>скобок в типе, таком какList<List<List<List<String>>>>, была бы неоднозначной, так как различные комбинации токенов>,>>и>>>могли бы представлять символы>>>>.
Рассмотрим два токена x и y в результирующем потоке ввода. Если x предшествует y, то мы говорим, что x находится слева от y и что y находится справа от x.
Например, в этом простом фрагменте кода:
class Empty {
}
мы говорим, что токен } находится справа от токена {, даже если он появляется в этом двумерном представлении вниз и влево от токена {. Эта конвенция относительно использования слов слева и справа позволяет нам говорить, например, об правом операнде бинарного оператора или о левой части присваивания.
Пробелы определяются как символ ASCII пробела, символ горизонтальной табуляции, символ подачи страницы и символы разделителей строк (§3.4).
символ ASCII HT, также известный как "горизонтальная табуляция"
символ ASCII FF, также известный как "подача страницы"
РазделительСтроки
Существуют два вида комментариев:
-
/*текст*/Традиционный комментарий: весь текст от ASCII-символов
/*до ASCII-символов*/игнорируется (как в C и C++). -
//текстКомментарий в конце строки: весь текст от ASCII-символов
//до конца строки игнорируется (как в C++).
Эти правила подразумевают все следующие свойства:
-
Комментарии не вложены.
-
/*и*/не имеют специального значения в комментариях, начинающихся с//. -
//не имеет специального значения в комментариях, начинающихся с/*или/**.
В результате, следующий текст является одним полным комментарием:
/* this comment /* // /** ends here: */
Лексическая грамматика подразумевает, что комментарии не встречаются внутри символьных литералов, строковых литералов или текстовых блоков (§3.10.4, §3.10.5, §3.10.6).
Идентификатор — это последовательность неограниченной длины символов-букв Java и цифр Java, первая из которых должна быть символом-буквой Java.
"Символ-буква Java" — это символ, для которого метод Character.isJavaIdentifierStart(int) возвращает true.
"Символ-буква-или-цифра Java" — это символ, для которого метод Character.isJavaIdentifierPart(int) возвращает true.
"Символы-буквы Java" включают прописные и строчные латинские буквы ASCII A-Z (\u0041-\u005a), а также a-z (\u0061-\u007a), и, по историческим причинам, знак доллара ASCII ($, или \u0024) и символ подчеркивания (_, или \u005f). Знак доллара следует использовать только в генерируемом автоматически исходном коде или, в редких случаях, для доступа к именам, существующим в legacy-системах. Символ подчеркивания может использоваться в идентификаторах, состоящих из двух или более символов, но не может использоваться как односимвольный идентификатор из-за того, что является ключевым словом.
"Цифры Java" включают цифры ASCII 0-9 (\u0030-\u0039).
Буквы и цифры могут быть взяты из всего набора символов Unicode, который поддерживает большинство письменных систем, используемых сегодня в мире, включая большие наборы для китайского, японского и корейского языков. Это позволяет программистам использовать в своих программах идентификаторы, написанные на родных языках.
Два идентификатора считаются одинаковыми только если, после игнорирования игнорируемых символов, у идентификаторов совпадают символы Unicode для каждой буквы или цифры. Игнорируемый символ — это символ, для которого метод Character.isIdentifierIgnorable(int) возвращает true. Идентификаторы, имеющие одинаковый внешний вид, могут быть разными.
Например, идентификаторы, состоящие из одиночных букв LATIN CAPITAL LETTER A (A, \u0041), LATIN SMALL LETTER A (a, \u0061), GREEK CAPITAL LETTER ALPHA (A, \u0391), CYRILLIC SMALL LETTER A (a, \u0430) и MATHEMATICAL BOLD ITALIC SMALL A (a, \ud835\udc82) все разные.
Композиционные символы Unicode отличаются от их канонических эквивалентов, представленных в разложенном виде. Например, LATIN CAPITAL LETTER A ACUTE (Á, \u00c1) отличается от LATIN CAPITAL LETTER A (A, \u0041), сразу за которым следует NON-SPACING ACUTE (´, \u0301) в идентификаторах. См. Стандарт Unicode, раздел 3.11 "Формы нормализации".
Примеры идентификаторов:
-
String -
i3 -
αρετη
-
MAX_VALUE -
isLetterOrDigit
Идентификатор никогда не имеет такой же написания (последовательности символов Unicode), как зарезервированное ключевое слово (§3.9), булево значение (§3.10.3) или null-литерал (§3.10.8), из-за правил токенизации (§3.5). Однако, идентификатор может иметь такое же написания, как контекстное ключевое слово, поскольку токенизация последовательности символов ввода как идентификатора или контекстного ключевого слова зависит от того, где последовательность появляется в программе.
Для облегчения распознавания контекстных ключевых слов, синтаксическая грамматика (§2.3) иногда запрещает определённые идентификаторы, определяя производство, принимающее только подмножество идентификаторов. Подмножества следующие:
TypeIdentifier используется при объявлении классов, интерфейсов и параметров типов (§8.1, §9.1, §4.4), и при ссылке на типы (§6.5). Например, имя класса должно быть TypeIdentifier, поэтому запрещено объявлять класс с именем permits, record, sealed, var или yield.
UnqualifiedMethodIdentifier используется, когда выражение вызова метода ссылается на метод по его простому имени (§6.5.7.1). Поскольку термин yield исключён из UnqualifiedMethodIdentifier, любой вызов метода с именем yield должен быть квалифицированным, что отличает вызов от оператора yield (§14.21).
51 последовательность символов, сформированных из ASCII-символов, зарезервированы для использования в качестве ключевых слов и не могут использоваться в качестве идентификаторов (§3.8). Ещё 17 последовательностей символов, также сформированных из ASCII-символов, могут интерпретироваться как ключевые слова или как другие токены в зависимости от контекста, в котором они появляются.
abstract continue for new switchassert default if package synchronizedboolean do goto private thisbreak double implements protected throwbyte else import public throwscase enum instanceof return transientcatch extends int short trychar final interface static voidclass finally long strictfp volatileconst float native super while_(underscore)
exports opens requires uses yieldmodule permits sealed varnon-sealed provides to whenopen record transitive with
Ключевые слова const и goto зарезервированы, даже если они в настоящее время не используются. Это может позволить компилятору Java генерировать более информативные сообщения об ошибках, если эти ключевые слова C++ неправильно используются в программах.
Ключевое слово strictfp устарело и не должно использоваться в новом коде.
Ключевое слово _ (подчёркивание) зарезервировано для возможного будущего использования в объявлениях параметров.
true и false не являются ключевыми словами, а являются булевыми литералами (§3.10.3).
null не является ключевым словом, а является литералом null (§3.10.8).
Во время сокращения входных символов до входных элементов (§3.5), последовательность входных символов, которая по смыслу соответствует контекстуальному ключевому слову, сокращается до контекстуального ключевого слова только в том случае, если выполняются оба следующих условия:
-
Последовательность распознаётся как терминал, указанный в соответствующем контексте синтаксической грамматики (§2.3), как следует:
-
Для
moduleиopen, когда они распознаются как терминалы в ModuleDeclaration (§7.7). -
Для
exports,opens,provides,requires,to,usesиwith, когда они распознаются как терминалы в ModuleDirective. -
Для
transitive, когда он распознаётся как терминал в RequiresModifier.Например, распознавание последовательности
requirestransitive;не использует RequiresModifier, поэтому терминtransitiveсокращается здесь до идентификатора, а не до контекстуального ключевого слова. -
Для
var, когда он распознаётся как терминал в LocalVariableType (§14.4) или LambdaParameterType (§15.27.1).В других контекстах попытка использовать
varкак идентификатор приведёт к ошибке, потому чтоvarне является TypeIdentifier (§3.8). -
Для
yield, когда он распознаётся как терминал в YieldStatement (§14.21).В других контекстах попытка использовать
yieldкак идентификатор приведёт к ошибке, потому чтоyieldне является ни TypeIdentifier, ни UnqualifiedMethodIdentifier. -
Для
record, когда он распознаётся как терминал в RecordDeclaration (§8.10). -
Для
non-sealed,permitsиsealed, когда они распознаются как терминалы в NormalClassDeclaration (§8.1) или NormalInterfaceDeclaration (§9.1). -
Для
when, когда он распознаётся как терминал в Guard (§14.11.1).
-
-
Последовательность не предшествует и не следует непосредственно входному символу, который соответствует JavaLetterOrDigit.
В общем случае случайное опускание пробелов в исходном коде приведёт к тому, что последовательность входных символов будет разложена на лексемы как идентификатор из-за правила «наибольшего возможного соответствия» (§3.2). Например, последовательность двенадцати входных символов p u b l i c s t a t i c всегда разлагается на лексемы как идентификатор publicstatic, а не как зарезервированные ключевые слова public и static. Если предполагается два токена, они должны быть разделены пробелами или комментарием.
Приведённое выше правило работает вместе с правилом «наибольшего возможного соответствия», чтобы получить интуитивный результат в контекстах, где могут появиться контекстуальные ключевые слова. Например, последовательность одиннадцати входных символов v a r f i l e n a m e обычно разлагается на лексемы как идентификатор varfilename, но в объявлении локальной переменной первые три входных символа предварительно распознаются как контекстуальное ключевое слово var в соответствии с первым условием вышеприведённого правила. Однако было бы неудобно игнорировать отсутствие пробелов в последовательности, распознавая следующие восемь входных символов как идентификатор filename. (Это означало бы, что последовательность подвергается различной разборке лексем в разных контекстах: идентификатор в большинстве контекстов, но контекстуальное ключевое слово и идентификатор в объявлениях локальных переменных.) Соответственно, второе условие предотвращает распознавание контекстуального ключевого слова var, поскольку следующий за ним входной символ f является JavaLetterOrDigit. Таким образом, последовательность v a r f
i l e n a m e разлагается на лексемы как идентификатор varfilename в объявлении локальной переменной.
Ещё один пример внимательного распознавания контекстуальных ключевых слов – последовательность из 15 входных символов n o n - s e a l
e d c l a s s. Эта последовательность обычно преобразуется в три токена — идентификатор non, оператор - и идентификатор sealedclass — но в объявлении обычного класса, где выполняется первое условие, первые десять входных символов предварительно распознаются как контекстуальное ключевое слово non-sealed. Чтобы избежать преобразования последовательности в два ключевых токена (non-sealed и class) вместо трёх не ключевых токенов и чтобы избежать награждения программиста за опускание пробелов перед class, второе условие предотвращает распознавание контекстуального ключевого слова. Поэтому последовательность n o n - s e a l e d c l a s s разлагается на три токена в объявлении класса.
В данном правиле первое условие зависит от деталей синтаксической грамматики, но компилятор языка программирования Java может реализовать это правило без полного разбора входной программы. Например, можно использовать эвристику для отслеживания контекстуального состояния разборщика лексем, если эвристика гарантирует, что допустимые использования контекстуальных ключевых слов разлагаются на лексемы как ключевые слова, а допустимые использования идентификаторов разлагаются на лексемы как идентификаторы. В качестве альтернативы компилятор может всегда разлагать контекстуальное ключевое слово на лексемы как идентификатор, оставив распознавание специальных случаев использования этих идентификаторов на более поздней фазе.
A литерал — это представление значения примитивного типа (§4.2), типа String (§4.3.3) или нулевого типа (§4.1) в исходном коде.
Целочисленный литерал может быть представлен в десятичной (основание 10), шестнадцатеричной (основание 16), восьмеричной (основание 8) или двоичной (основание 2) системе счисления.
l L Целочисленный литерал имеет тип long, если он имеет суффикс с ASCII буквой L или l (ell); в противном случае он имеет тип int (§4.2.1).
Суффикс L предпочтительнее, так как букву l (ell) часто трудно отличить от цифры 1 (один).
Разделители подчеркивания допускаются между цифрами, обозначающими целое число.
В шестнадцатеричном или двоичном литерале целое число обозначается только цифрами после символов 0x или 0b и перед любым суффиксом типа. Поэтому подчеркивания не могут появляться непосредственно после 0x или 0b, или после последней цифры в числе.
В десятичном или восьмеричном литерале целое число обозначается всеми цифрами в литерале перед любым суффиксом типа. Поэтому подчеркивания не могут появляться перед первой цифрой или после последней цифры в числе. Подчеркивания могут появляться после начальной 0 в восьмеричном числе (поскольку 0 — это цифра, обозначающая часть целого числа) и после начальной ненулевой цифры в ненулевом десятичном литерале.
Десятичная цифра — это либо одиночная ASCII цифра 0, представляющая ноль, или состоит из ASCII цифры от 1 до 9, за которой необязательно следуют одна или несколько ASCII цифр от 0 до 9, перемежающиеся подчеркиваниями, представляющими положительное целое число.
1 2 3 4 5 6 7 8 9 _ {_} Шестнадцатеричная цифра состоит из ведущих ASCII символов 0x или 0X, за которыми следуют одна или несколько ASCII шестнадцатеричных цифр, перемежающиеся подчеркиваниями, и может представлять положительное, нулевое или отрицательное целое число.
Шестнадцатеричные цифры со значениями от 10 до 15 представлены ASCII буквами a до f или A до F соответственно; каждая буква, используемая в качестве шестнадцатеричной цифры, может быть заглавной или строчной.
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F Производство ШестнадцатеричнаяЦифра выше взято из §3.3.
Восьмеричная цифра состоит из ASCII цифры 0, за которой следует одна или несколько ASCII цифр от 0 до 7, перемежающиеся подчеркиваниями, и может представлять положительное, нулевое или отрицательное целое число.
0 1 2 3 4 5 6 7 Обратите внимание, что восьмеричные числа всегда состоят из двух или более цифр, так как 0 в одиночку всегда считается десятичным числом — не то, что это имеет большое значение на практике, так как числа 0, 00 и 0x0 представляют одно и то же целое значение.
Двоичная цифра состоит из ведущих ASCII символов 0b или 0B, за которыми следуют одна или несколько ASCII цифр 0 или 1, перемежающиеся подчеркиваниями, и может представлять положительное, нулевое или отрицательное целое число.
0 1 Наибольшая десятичная литерал типа int равна 2147483648 (231).
Все десятичные литералы от 0 до 2147483647 могут встречаться в любом месте, где может стоять int литерал. Десятичная литерал 2147483648 может встречаться только как операнд унарного минуса - (§15.15.4).
Ошибка компиляции, если десятичная литерал 2147483648 встречается где-либо, кроме как операндом унарного минуса; или если десятичная литерал типа int больше, чем 2147483648 (231).
Наибольшие положительные шестнадцатеричные, восьмеричные и двоичные литералы типа int, каждый из которых представляет десятичное значение 2147483647 (231-1), соответственно:
-
0x7fff_ffff, -
0177_7777_7777, и -
0b0111_1111_1111_1111_1111_1111_1111_1111
Наименьшие отрицательные шестнадцатеричные, восьмеричные и двоичные литералы типа int, каждый из которых представляет десятичное значение -2147483648 (-231), соответственно:
-
0x8000_0000, -
0200_0000_0000, и -
0b1000_0000_0000_0000_0000_0000_0000_0000
Следующие шестнадцатеричные, восьмеричные и двоичные литералы представляют десятичное значение -1:
-
0xffff_ffff, -
0377_7777_7777, и -
0b1111_1111_1111_1111_1111_1111_1111_1111
Ошибка компиляции, если шестнадцатеричный, восьмеричный или двоичный int литерал не помещается в 32 бита.
Наибольшая десятичная литерал типа long равна 9223372036854775808L (263).
Все десятичные литералы от 0L до 9223372036854775807L могут встречаться в любом месте, где может стоять long литерал. Десятичная литерал 9223372036854775808L может встречаться только как операнд унарного минуса - (§15.15.4).
Ошибка компиляции, если десятичная литерал 9223372036854775808L встречается где-либо, кроме как операндом унарного минуса; или если десятичная литерал типа long больше, чем 9223372036854775808L (263).
Наибольшие положительные шестнадцатеричные, восьмеричные и двоичные литералы типа long, каждый из которых представляет десятичное значение 9223372036854775807L (263-1), соответственно:
-
0x7fff_ffff_ffff_ffffL, -
07_7777_7777_7777_7777_7777L, и -
0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L
Наименьшие отрицательные шестнадцатеричные, восьмеричные и двоичные литералы типа long, каждый из которых представляет десятичное значение -9223372036854775808L (-263), соответственно:
-
0x8000_0000_0000_0000L, -
010_0000_0000_0000_0000_0000L, и -
0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L
Следующие шестнадцатеричные, восьмеричные и двоичные литералы представляют десятичное значение -1L:
-
0xffff_ffff_ffff_ffffL, -
017_7777_7777_7777_7777_7777L, и -
0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L
Ошибка компиляции, если шестнадцатеричный, восьмеричный или двоичный long литерал не помещается в 64 бита.
Примеры int литералов:
0 2 0372 0xDada_Cafe 1996 0x00_FF__00_FF
Примеры long литералов:
0l 0777L 0x100000000L 2_147_483_648L 0xC0B0L
Числовой литерал с плавающей точкой состоит из следующих частей: целая часть, десятичная или шестнадцатеричная точка (представленная символом ASCII точки), дробная часть, показатель степени и суффикс типа.
Числовой литерал с плавающей точкой может быть представлен в десятичной (основание 10) или шестнадцатеричной (основание 16) форме.
Для десятичных числовых литералов с плавающей точкой требуется хотя бы одна цифра (в целой или дробной части) и либо десятичная точка, либо показатель степени, либо суффикс типа float. Все остальные части являются необязательными. Показатель степени, если он присутствует, обозначается символами ASCII e или E, за которыми следует необязательно со знаком целое число.
Для шестнадцатеричных числовых литералов с плавающей точкой требуется хотя бы одна цифра (в целой или дробной части), показатель степени является обязательным, а суффикс типа float — необязательным. Показатель степени обозначается символами ASCII p или P, за которыми следует необязательно со знаком целое число.
Подчеркивания разрешены в качестве разделителей между цифрами, обозначающими целую часть, между цифрами, обозначающими дробную часть, и между цифрами, обозначающими показатель степени.
e E + - f F d D p P Числовой литерал с плавающей точкой имеет тип float, если он имеет суффикс из символов ASCII F или f; в противном случае его тип равен double, и он может необязательно иметь суффикс из символов ASCII D или d.
Элементы типов float и double представляют собой те значения, которые могут быть представлены в формате чисел с плавающей точкой IEEE 754 binary32 и IEEE 754 binary64 соответственно (§4.2.3).
Подробное описание правильного преобразования входной строковой представления числа с плавающей точкой в внутреннее представление IEEE 754 с плавающей точкой приведено для методов valueOf класса Float и класса Double пакета java.lang.
Наибольшие и наименьшие положительные литералы типа float следующие:
-
Наибольшее положительное конечное значение
floatчисленно равно (2 - 2-23) ⋅ 2127.Наиболее короткий десятичный литерал, который округляется до этого значения, равен
3.4028235e38f.Шестнадцатеричный литерал для этого значения равен
0x1.fffffeP+127f. -
Наименьшее положительное конечное ненулевое значение
floatчисленно равно 2-149.Наиболее короткий десятичный литерал, который округляется до этого значения, равен
1.4e-45f.Два шестнадцатеричных литерала для этого значения равны
0x0.000002P-126fи0x0.0_0000_0000_0001P-1022.
Наибольшие и наименьшие положительные литералы типа double следующие:
-
Наибольшее положительное конечное значение
doubleчисленно равно (2 - 2-52) ⋅ 21023.Наиболее короткий десятичный литерал, который округляется до этого значения, равен
1.7976931348623157e308.Шестнадцатеричный литерал для этого значения равен
0x1.f_ffff_ffff_ffffP+1023. -
Наименьшее положительное конечное ненулевое значение
doubleчисленно равно 2-1074.Наиболее короткий десятичный литерал, который округляется до этого значения, равен
4.9e-324.Два шестнадцатеричных литерала для этого значения равны
0x0.0_0000_0000_0001P-1022и0x1.0P-1074.
Если ненулевой числовой литерал с плавающей точкой слишком большой, так что при округленном преобразовании в его внутреннее представление он становится бесконечностью IEEE 754, это является ошибкой на этапе компиляции.
Программа может представлять бесконечности без возникновения ошибки на этапе компиляции, используя константные выражения, такие как 1f/0f или -1d/0d, или используя предопределенные константы POSITIVE_INFINITY и NEGATIVE_INFINITY классов Float и Double.
Если ненулевой числовой литерал с плавающей точкой слишком мал, так что при округленном преобразовании в его внутреннее представление он становится нулём, это является ошибкой на этапе компиляции.
Ошибка на этапе компиляции не возникает, если ненулевой числовой литерал с плавающей точкой имеет малое значение, которое при округленном преобразовании в его внутреннее представление становится ненулевым числом с пониженной точностью.
Предопределённые константы, представляющие значения «не число», определены в классах Float и Double как Float.NaN и Double.NaN.
Примеры числовых литералов с плавающей точкой:
1e1f 2.f .3f 0f 3.14f 6.022137e+23f
Примеры числовых литералов с плавающей точкой:
1e1 2. .3 0.0 3.14 1e-9d 1e137
Тип boolean имеет два значения, представленные булевыми литералами true и false, образованными из символов ASCII.
true false Булевый литерал всегда имеет тип boolean (§4.2.5).
Литерал символа записывается как символ или последовательность управляющих символов (§3.10.7), заключенные в одиночные ASCII кавычки. (Символ одиночной кавычки, или апострофа, это \u0027.)
Литерал символа всегда имеет тип char (§4.2.1).
Содержимое литерала символа — это SingleCharacter или EscapeSequence, следующие за открывающей '.
Ошибка компиляции, если символ, следующий за содержимым, не является '.
Ошибка компиляции, если разделитель строки (§3.4) появляется после открывающей ' и перед закрывающей '.
Символы CR и LF никогда не являются InputCharacter; каждый из них распознается как LineTerminator, поэтому не может появляться в литерале символа, даже в последовательности управляющих символов \ LineTerminator.
Символ, представленный литералом символа — это содержимое литерала символа со всеми последовательностями управляющих символов, интерпретированных, как если бы они были выполнены String.translateEscapes на содержимом.
Литералы символов могут представлять только единицы кодировки UTF-16 (§3.1), т.е. они ограничены значениями от \u0000 до \uffff. Дополнительные символы должны быть представлены либо как пара суррогатов в последовательности char, либо как целое число, в зависимости от API, с которым они используются.
Ниже приведены примеры литералов символов:
-
'a' -
'%' -
'\t' -
'\\' -
'\'' -
'\u03a9' -
'\uFFFF' -
'\177' -
'™'
Поскольку эскапированные Unicode-последовательности обрабатываются очень рано, неверно писать '\u000a' для литерала символа, значение которого является символом новой строки (LF); эскапированная Unicode-последовательность \u000a преобразуется в фактический символ новой строки на этапе 1 (§3.3), а символ новой строки становится LineTerminator на этапе 2 (§3.4), поэтому литерал символа недействителен на этапе 3. Вместо этого следует использовать последовательность управляющих символов '\n'. Аналогично, неверно писать '\u000d' для литерала символа, значение которого является символом возврата каретки (CR). Вместо этого следует использовать '\r'. Наконец, невозможно написать '\u0027' для литерала символа, содержащего апостроф (').
В языках C и C++ литерал символа может содержать представления более чем одного символа, но значение такого литерала символа определяется реализацией. В языке программирования Java литерал символа всегда представляет ровно один символ.
Литерал строки состоит из нуля или более символов, заключенных в двойные кавычки. Символы, такие как новые строки, могут быть представлены с помощью последовательностей управляющих символов (§3.10.7).
Литерал строки всегда имеет тип String (§4.3.3).
Содержимое литерала строки — это последовательность символов, которая начинается сразу после открывающей " и заканчивается непосредственно перед соответствующей закрывающей ".
Ошибка компиляции, если разделитель строки (§3.4) появляется после открывающей " и перед соответствующей закрывающей ".
Символы CR и LF никогда не являются InputCharacter; каждый из них распознается как LineTerminator, поэтому не может появляться в литерале строки, даже в последовательности управляющих символов \ LineTerminator.
Строка, представленная литералом строки, — это содержимое литерала строки с интерпретированными всеми последовательностями управляющих символов, как если бы они были выполнены String.translateEscapes на содержимом.
Ниже приведены примеры литералов строк:
"" // the empty string
"\"" // a string containing " alone
"This is a string" // a string containing 16 characters
"This is a " + // actually a string-valued constant expression,
"two-line string" // formed from two string literals
Поскольку эскапированные Unicode-последовательности обрабатываются очень рано, неверно писать "\u000a" для литерала строки, содержащего один символ новой строки (LF); эскапированная Unicode-последовательность \u000a преобразуется в фактический символ новой строки на этапе 1 (§3.3), а символ новой строки становится LineTerminator на этапе 2 (§3.4), поэтому литерал строки недействителен на этапе 3. Вместо этого следует использовать последовательность управляющих символов "\n". Аналогично, неверно писать "\u000d" для литерала строки, содержащего один символ возврата каретки (CR). Вместо этого следует использовать "\r". Наконец, невозможно написать "\u0022" для литерала строки, содержащего двойную кавычку (").
Длинный литерал строки всегда можно разбить на более короткие части и записать как (возможно, заключенное в скобки) выражение, использующее оператор конкатенации строк + (§15.18.1).
Во время выполнения литерал строки является ссылкой на экземпляр класса String (§4.3.3), который обозначает строку, представленную литералом строки.
Кроме того, литерал строки всегда ссылается на тот же экземпляр класса String. Это потому, что литералы строк — или, более обобщенно, строки, которые являются значениями константных выражений (§15.29) — «интернируются» для совместного использования уникальных экземпляров, как если бы они были выполнены методом String.intern (§12.5).
Пример 3.10.5-1. Литералы строк
Программа, состоящая из единицы компиляции (§7.3):
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.println(hello == "Hello");
System.out.println(Other.hello == hello);
System.out.println(other.Other.hello == hello);
System.out.println(hello == ("Hel"+"lo"));
System.out.println(hello == ("Hel"+lo));
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
и единица компиляции:
package other;
public class Other { public static String hello = "Hello"; }
выводит:
true true true true false true
Этот пример иллюстрирует шесть пунктов:
-
Литералы строк в одном классе и пакете представляют ссылки на один и тот же объект
String(§4.3.1). -
Литералы строк в разных классах в одном пакете представляют ссылки на один и тот же объект
String. -
Литералы строк в разных классах в разных пакетах также представляют ссылки на один и тот же объект
String. -
Строки, конкатенированные из константных выражений (§15.29), вычисляются во время компиляции и затем обрабатываются как если бы они были литералами.
-
Строки, вычисленные путем конкатенации во время выполнения, создаются заново и, следовательно, различны.
-
Результат явного интернирования вычисленной строки — тот же объект
String, что и любой существующий литерал строки с таким же содержимым.
Блок текста состоит из нуля или более символов, заключенных в открывающие и закрывающие разделители. Символы могут быть представлены с помощью последовательностей управляющих символов (§3.10.7), но символы новой строки и двойной кавычки, которые должны быть представлены с помощью последовательностей управляющих символов в строковой литерале (§3.10.5), могут быть представлены непосредственно в блоке текста.
Следующие продукции из §3.3, §3.4 и §3.6 приведены здесь для удобства:
символ ASCII HT, также известный как "горизонтальная табуляция"
символ ASCII FF, также известный как "форма подачи"
РазделительСтрок
символ ASCII CR, также известный как "возврат каретки"
символ ASCII CR, за которым следует символ ASCII LF
Блок текста всегда имеет тип String (§4.3.3).
Открывающий разделитель — это последовательность, начинающаяся с трёх символов двойной кавычки ("""), продолжающаяся нулём или более символами пробела, табуляции и подачи формы, и заканчивающаяся разделителем строки.
Закрывающий разделитель — это последовательность из трёх символов двойной кавычки.
Содержание блока текста — это последовательность символов, начинающаяся сразу после разделителя строки открывающего разделителя и заканчивающаяся перед первым символом двойной кавычки закрывающего разделителя.
В отличие от строковой литералы (§3.10.5), появление разделителя строки в содержимом блока текста не является ошибкой компиляции.
Пример 3.10.6-1. Блоки текста
При необходимости многострочных строк блок текста обычно более читабелен, чем конкатенация строковых литералов. Например, сравните эти альтернативные представления фрагмента HTML:
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
Ниже приведены примеры блоков текста:
class Test {
public static void main(String[] args) {
// The six characters w i n t e r
String season = """
winter""";
// The seven characters w i n t e r LF
String period = """
winter
""";
// The ten characters H i , SP " B o b " LF
String greeting = """
Hi, "Bob"
""";
// The eleven characters H i , LF SP " B o b " LF
String salutation = """
Hi,
"Bob"
""";
// The empty string (zero length)
String empty = """
""";
// The two characters " LF
String quote = """
"
""";
// The two characters \ LF
String backslash = """
\\
""";
}
}
Использование последовательностей управляющих символов \n и \" для представления символа новой строки и символа двойной кавычки соответственно допускается в блоке текста, хотя обычно это не требуется. Исключением является случай, когда встречаются три последовательных символа двойной кавычки, которые не предназначены для закрывающего разделителя """ — в этом случае необходимо экранировать как минимум один символ двойной кавычки, чтобы избежать имитации закрывающего разделителя.
Пример 3.10.6-2. Последовательности управляющих символов в блоках текста
В следующей программе значение переменной story было бы менее читабельным, если бы отдельные символы двойной кавычки были экранированы:
class Story1 {
public static void main(String[] args) {
String story = """
"When I use a word," Humpty Dumpty said,
in rather a scornful tone, "it means just what I
choose it to mean - neither more nor less."
"The question is," said Alice, "whether you
can make words mean so many different things."
"The question is," said Humpty Dumpty,
"which is to be master - that's all."
""";
}
}
Если программа изменена таким образом, чтобы поместить закрывающий разделитель в последней строке содержимого, возникает ошибка, поскольку первые три последовательных символа двойной кавычки в последней строке преобразуются (§3.2) в закрывающий разделитель """, и, таким образом, остаётся лишний символ двойной кавычки:
class Story2 {
public static void main(String[] args) {
String story = """
"When I use a word," Humpty Dumpty said,
in rather a scornful tone, "it means just what I
choose it to mean - neither more nor less."
"The question is," said Alice, "whether you
can make words mean so many different things."
"The question is," said Humpty Dumpty,
"which is to be master - that's all.""""; // error
}
}
Ошибка может быть устранена путём экранирования последнего символа двойной кавычки в содержимом:
class Story3 {
public static void main(String[] args) {
String story = """
"When I use a word," Humpty Dumpty said,
in rather a scornful tone, "it means just what I
choose it to mean - neither more nor less."
"The question is," said Alice, "whether you
can make words mean so many different things."
"The question is," said Humpty Dumpty,
"which is to be master - that's all.\""""; // OK
}
}
Если блок текста предназначен для обозначения другого блока текста, рекомендуется экранировать первый символ двойной кавычки открывающего и закрывающего разделителей вложенного блока:
class Code {
public static void main(String[] args) {
String text = """
The quick brown fox jumps over the lazy dog
""";
String code =
"""
String text = \"""
The quick brown fox jumps over the lazy dog
\""";
""";
}
}
Строка, представленная блоком текста, — это не буквальная последовательность символов в содержимом. Вместо этого строка, представленная блоком текста, является результатом применения следующих преобразований к содержимому в указанном порядке:
-
Разделители строк нормализуются до символа ASCII LF следующим образом:
-
Символ ASCII CR, за которым следует символ ASCII LF, преобразуется в символ ASCII LF.
-
Символ ASCII CR преобразуется в символ ASCII LF.
-
-
Случайные пробелы удаляются, как если бы они выполнялись
String.stripIndentна символах, полученных на шаге 1. -
Последовательности управляющих символов интерпретируются, как если бы они выполнялись
String.translateEscapesна символах, полученных на шаге 2.
Когда в этом спецификации говорится, что блок текста содержит определённый символ или последовательность символов, или что определённый символ или последовательность символов в блоке текста, это означает, что строка, представленная блоком текста (в отличие от буквальной последовательности символов в содержимом), содержит этот символ или последовательность символов.
Пример 3.10.6-3. Порядок преобразований содержимого блока текста
Интерпретация последовательностей управляющих символов в последнюю очередь позволяет программистам использовать \n, \f и \r для вертикального форматирования строки без влияния на нормализацию разделителей строк и использовать \b и \t для горизонтального форматирования строки без влияния на удаление случайных пробелов. Например, рассмотрите этот блок текста, в котором упоминается последовательность управляющих символов \r (CR):
String html = """
<html>\r
<body>\r
<p>Hello, world</p>\r
</body>\r
</html>\r
""";
Последовательности управляющих символов \r интерпретируются не ранее, чем после нормализации разделителей строк до LF. Используя Unicode-экранирование для визуализации LF (\u000A) и CR (\u000D), и используя | для визуализации левого отступа, строка, представленная блоком текста, имеет вид:
|<html>\u000D\u000A | <body>\u000D\u000A | <p>Hello, world</p>\u000D\u000A | </body>\u000D\u000A |</html>\u000D\u000A
Во время выполнения блок текста является ссылкой на экземпляр класса String, который обозначает строку, представленную блоком текста.
Кроме того, блок текста всегда ссылается на один и тот же экземпляр класса String. Это происходит потому, что строки, представленные блоками текста, или, более обще, строки, являющиеся значениями константных выражений (§15.29), «интернируются», чтобы иметь уникальные экземпляры, как если бы выполнялся метод String.intern (§12.5).
Пример 3.10.6-4. Блоки текста оцениваются как String
Блоки текста могут использоваться там, где разрешено выражение типа String, например, в конкатенации строк (§15.18.1), в вызове методов экземпляров String и в аннотациях с элементами String:
System.out.println("ab" + """
cde
""");
String cde = """
abcde""".substring(2);
String math = """
1+1 equals \
""" + String.valueOf(2);
@Preconditions("""
rate > 0 &&
rate <= MAX_REFRESH_RATE
""")
public void setRefreshRate(int rate) { ... }
В литералах символов, строковых литералах и блоках текста (§3.10.4, §3.10.5, §3.10.6) последовательности экранирования позволяют представлять некоторые неграфические символы без использования Unicode-экранирования (§3.3), а также символы одиночной кавычки, двойной кавычки и обратной косой черты.
\ b (возврат на один символ назад BS, Unicode \u0008) \ s (пробел SP, Unicode \u0020) \ t (горизонтальная табуляция HT, Unicode \u0009) \ n (новая строка LF, Unicode \u000a) \ f (форма подачи FF, Unicode \u000c) \ r (возврат каретки CR, Unicode \u000d) \ LineTerminator (продолжение строки, без представления Unicode) \ " (двойная кавычка ", Unicode \u0022) \ ' (одинарная кавычка ', Unicode \u0027) \ \ (обратная косая черта \, Unicode \u005c) OctalEscape (восьмеричное значение, Unicode
\u0000 по \u00ff) 0 1 2 3 4 5 6 7 0 1 2 3 Производство OctalDigit выше взято из §3.10.1. Восьмеричные экранирования предоставляются для совместимости с C, но могут выражать только значения Unicode \u0000 по \u00FF, поэтому обычно предпочтительнее использовать Unicode-экранирование.
Ошибка компиляции, если символ, следующий за обратной косой чертой в последовательности экранирования, не является LineTerminator или ASCII b, s, t, n, f, r, ", ', \, 0, 1, 2, 3, 4, 5, 6 или 7.
Последовательность экранирования в содержимом литерала символа, строкового литерала или блока текста интерпретируется заменой его \ и последующего символа(ов) одним символом, обозначаемым Unicode-экранированием в грамматике EscapeSequence. Последовательность экранирования продолжения строки не имеет соответствующего Unicode-экранирования, поэтому интерпретируется заменой её ничем.
Последовательность экранирования продолжения строки может появляться в блоке текста, но не может появляться в литерале символа или строковом литерале, так как каждый из них запрещает LineTerminator.
Тип null имеет одно значение — нулевую ссылку, представленную литералом null null, образованным из ASCII-символов.
nullЛитерал null всегда относится к типу null (§4.1).
Двенадцать токенов, образованных из ASCII-символов, являются разделителями (знаками препинания).
( ) { } [ ] ; , . ... @ :: 38 токенов, образованных из ASCII-символов, являются операторами.
= > < ! ~ ? :->== >= <= != && || ++ --+ - * / & | ^ % << >> >>>+= -= *= /= &= |= ^= %= <<= >>= >>>=
© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.