Глава 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 устарело и не должно использоваться в новом коде.
Ключевое слово _ (нижняя черта) может использоваться в определенных объявлениях вместо идентификатора (§6.1).
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 никогда не являются Входными символами; каждый из них распознаётся как Разделитель строки, поэтому не может встречаться в символьном литерале, даже в последовательности управляющих символов \ Разделитель строки.
Символ, представленный символьным литералом, — это содержимое символьного литерала с интерпретацией всех последовательностей управляющих символов, как будто выполняется String.translateEscapes на содержимом.
Символьные литералы могут представлять только единицы кодирования UTF-16 (§3.1), т.е. ограничены значениями от \u0000 до \uffff. Дополнительные символы должны быть представлены либо парой суррогатов в последовательности char, либо в виде целого числа, в зависимости от API, с которым они используются.
Ниже приведены примеры char литералов:
-
'a' -
'%' -
'\t' -
'\\' -
'\'' -
'\u03a9' -
'\uFFFF' -
'\177' -
'™'
Поскольку эскапированные Unicode-последовательности обрабатываются очень рано, неверно писать '\u000a' для символьного литерала, значением которого является символ перевода строки (LF); эскапированная последовательность Unicode \u000a преобразуется в фактический символ перевода строки на этапе 1 (§3.3), а символ перевода строки становится Разделителем строки на этапе 2 (§3.4), поэтому символьный литерал недействителен на этапе 3. Вместо этого следует использовать последовательность управляющих символов '\n'. Аналогично, неверно писать '\u000d' для символьного литерала, значением которого является символ возврата каретки (CR). Вместо этого используйте '\r'. Наконец, невозможно написать '\u0027' для символьного литерала, содержащего апостроф (').
В C и C++ символьный литерал может содержать представление нескольких символов, но значение такого символьного литерала определяется реализацией. В языке программирования Java символьный литерал всегда представляет ровно один символ.
Строковый литерал состоит из нуля или более символов, заключённых в двойные кавычки. Символы, такие как новые строки, могут быть представлены последовательностями управляющих символов (§3.10.7).
Строковый литерал всегда имеет тип String (§4.3.3).
Содержимое строкового литерала — это последовательность символов, начинающаяся непосредственно после открывающей " и заканчивающаяся непосредственно перед соответствующей закрывающей ".
Ошибка компиляции, если после открывающей " и перед соответствующей закрывающей " встречается разделитель строки (§3.4).
Символы CR и LF никогда не являются Входными символами; каждый из них распознаётся как Разделитель строки, поэтому не может встречаться в строковом литерале, даже в последовательности управляющих символов \ Разделитель строки.
Строка, представленная строковым литералом, — это содержимое строкового литерала с интерпретацией всех последовательностей управляющих символов, как будто выполняется 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), а символ перевода строки становится Разделителем строки на этапе 2 (§3.4), поэтому строковый литерал недействителен на этапе 3. Вместо этого следует использовать последовательность управляющих символов "\n". Аналогично, неверно писать "\u000d" для строкового литерала, содержащего только символ возврата каретки (CR). Вместо этого используйте "\r". Наконец, невозможно написать "\u0022" для строкового литерала, содержащего двойную кавычку (").
Длинный строковый литерал всегда можно разбить на более короткие части и записать как выражение (возможно, в скобках) с использованием оператора конкатенации строк + (§15.18.1).
Во время выполнения строковый литерал — это ссылка на экземпляр класса String (§4.3.3), который обозначает строку, представленную строковым литералом.
Кроме того, строковый литерал всегда ссылается на один и тот же экземпляр класса String. Это потому, что строковые литералы — или, более общо, строки, которые являются значениями константных выражений (§15.29) — «интеризируются» (interned), чтобы иметь уникальные экземпляры, как будто выполняется метод 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, что и любой существующий строковый литерал с тем же содержимым.
Блок текста состоит из нуля или более символов, заключённых в открывающие и закрывающие разделители. Символы могут быть представлены последовательностями escape (§3.10.7), но символы новой строки и двойной кавычки, которые должны быть представлены последовательностями escape в строковой литерале (§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 = """
\\
""";
}
}
Использование последовательностей escape \n и \" для представления символа новой строки и символа двойной кавычки соответственно допускается в блоке текста, хотя обычно не требуется. Исключением является случай, когда встречаются три последовательных символа двойной кавычки, которые не предназначены для обозначения закрывающего разделителя """ — в этом случае необходимо экранировать по крайней мере один из символов двойной кавычки, чтобы избежать имитации закрывающего разделителя.
Пример 3.10.6-2. Последовательности escape в блоках текста
В следующей программе значение переменной 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. -
Последовательности escape интерпретируются, как если бы выполнялось
String.translateEscapesна символах, полученных на шаге 2.
Когда в этом спецификации говорится, что блок текста содержит определённый символ или последовательность символов, или что определённый символ или последовательность символов находятся в блоке текста, это означает, что строка, представленная блоком текста (в отличие от буквальной последовательности символов в содержимом), содержит символ или последовательность символов.
Пример 3.10.6-3. Порядок преобразований содержимого блока текста
Интерпретация последовательностей escape в последнюю очередь позволяет программистам использовать \n, \f и \r для вертикального форматирования строки без влияния на нормализацию переходов на новую строку и использовать \b и \t для горизонтального форматирования строки без влияния на удаление случайных пробелов. Например, рассмотрим этот блок текста, который упоминает последовательность escape \r (CR):
String html = """
<html>\r
<body>\r
<p>Hello, world</p>\r
</body>\r
</html>\r
""";
Последовательности escape \r не интерпретируются до тех пор, пока переносы строк не будут нормализованы до LF. Используя Unicode escape для визуализации 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.