Skip to content

Latest commit

 

History

History
712 lines (458 loc) · 35.6 KB

03-词法结构.md

File metadata and controls

712 lines (458 loc) · 35.6 KB

第三章 词法结构

此章指定了 Java 编程语言的词法结构。

程序用 Unicode(3.1)编写,但仅使用 ASCII 字符来提供词法转换(3.2),这样 Unicode 转义(3.3)可以用于包含任何 Unicode 字符。在维护一致的行号时,定义了行终止符(3.4),以便支持现存主机系统的不同转换。

由词法转换产生的 Unicode 字符被简化为一个输入元素(3.5)序列,这些输入元素是空格(3.6)、注释(3.7)和记号。记号是语法文法的标识符(3.8)、关键字(3.9)、字面量(3.10)、分隔符(3.11)和运算符(3.12)。

3.1 Unicode

使用 Unicode 字符集编写程序。有关此字符集和其相关字符编码的信息可以在 http://www.unicode.org/ 上找到。

Java SE 平台在其演进时跟踪 Unicode 标准。在文档的类 Character 中指定一个给定发行版使用的 Unicode 的精确版本。

Versions of the Java programming language prior to JDK 1.1 used Unicode 1.1.5. Upgrades to newer versions of the Unicode Standard occurred in JDK 1.1 (to Unicode 2.0), JDK 1.1.7 (to Unicode 2.1), Java SE 1.4 (to Unicode 3.0), Java SE 5.0 (to Unicode 4.0), Java SE 7 (to Unicode 6.0), and Java SE 8 (to Unicode 6.2).

Unicode 标准最初设计为固定宽度的 16 位字符编码。此后,它已被更改为允许需要多于 16 位的表示的字符。合法码点的范围现在是 U+0000 到 U+10FFFF,使用十六进制 U+n 表示法。码点大于 U+FFFF 的字符称为补充字符。为了表示仅使用 16 位单元的字符的完整范围,Unicode 标准定义了一个称为 UTF-16 的编码。在这种编码中,补充字符表示为 16 位码点对,第一个来自替代范围,(U+D800 到 U+DBFF),第二个来自地替代范围(U+DC00 到 U+DFFF)。对于在范围 U+0000 到 U+FFFF 中的字符,码点值和 UTF-16 的代码单元相同。

Java 编程语言使用 UTF-16 编码表示 16 位代码单元序列中的文本。

Some APIs of the Java SE platform, primarily in the Character class, use 32-bit integers to represent code points as individual entities. The Java SE platform provides methods to convert between 16-bit and 32-bit representations.

此规范在表示相关的地方使用术语码点和UTF-16代码单元,在表示与讨论无关的地方使用通用术语字符。

除注释(3.7)、标识符以及字符和字符串文本(3.10.4,3.10.5)的内容外,程序中的所有输入元素(3.5)只从ASCII字符(或生成ASCII字符的Unicode转义(3.3))中形成。

ASCII (ANSI X3.4) is the American Standard Code for Information Interchange. The first 128 characters of the Unicode UTF-16 encoding are the ASCII characters.

3.2 词法转换

使用如下三个词法转换步骤,将一个原始 Unicode 字符流转换为一个记号序列,依次应用:

  1. 将原始 Unicode 字符流中的 Unicode 转义转换为相应的 Unicode 字符。一个 \uxxxx 形式的 Unicode 转义,其中 xxxx 是一个十六进制值,表示 UTF-16 代码单元,其编码是 xxxx。此步骤允许任何程序仅使用 ASCII 字符表达。

  2. 将步骤 1 中产生的 Unicode 流转换为输入字符和行结束符(3.4)的流。

  3. 将步骤 2 中产生的输入字符和行结束符的流转换为输入元素(3.5)序列,在丢弃空格(3.6)和注释(3.7)之后,将包含句记号(3.5),这些记号是句法文法(2.3)的终端符号。

在每个步骤中都使用尽可能长的转换,即使结果最终不会生成正确的程序,而另一个词法转换也会这样。有一个异常:如果在类型上下文中发生词法转换,输入流有两个或更多连续的 > 字符,其后跟一个非 > 字符,则每个 > 字符必须被转换成数值比较运算符 > 的记号。

3.3 Unicode 转义

Java 编程语言的编译器(“Java 编译器”)首先识别其输入中的 Unicode 转义,为了指示的十六进制值,将后跟四个十六进制数字的 ASCII 字符 \u 转换为 UTF-16 代码单元(3.1),不更改其它字符直接传递它们。表示补充字符需要两个连续的 Unicode 转义。此转换步骤生成 Unicode 输入字符序列。

UnicodeInputCharacter:
  UnicodeEscape
  RawInputCharacter

UnicodeEscape:
  \ UnicodeMarker HexDigit HexDigit HexDigit HexDigit

UnicodeMarker:
  u {u}

HexDigit:
  (one of)
  0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F

RawInputCharacter:
  any Unicode character

这里的 \ 、 u 和十六进制数字都是 ASCII 字符。

除去语法隐含的处理外,对于每个原始的反斜线 \ 输入字符,输入处理必须考虑它前面有多少个其他的 \ 字符连续,将它与非 \ 字符或输入流的开头分开。如果这个数字是偶数,则该 \ 可以开始一个 Unicode 转义;如果这个数字是奇数,则该 \ 不能开始一个 Unicode 转义。

    例如,原始输入"\u2122=\u2122" 生成十一个字符 "\ \ u 2 1 2 2 = ™"(\u2122是字符 ™ 的 Unicode 编码)。

如果一个合适的 \ 后面没有跟着 u,则将它视为一个 RawInputCharacter,并保持为转义 Unicode 流的一部分。

如果一个合适的 \ 后面跟着 u,或多于一个 u,并且最后一个 u 后面没有跟着四个十六进制数字,则发生一个编译时错误。

Unicode 转义产生的字符不参与进一步的 Unicode 转义。

    例如,原始输入 \u005ou005a 产生六个字符 \ u 0 0 5 a,因为 005o 是 \ 的 Unicode 值。它不会产生字符 Z,其是 Unicode 字符 005a,因为产生自 \u005o 的 \ 不会被解释为进一步 Unicode 转义的开始。

Java 编程语言指定了一种标准的将用 Unicode 编写的程序转换为 ASCII 的方式,其将程序改变为可以被基于 ASCII 的工具处理的形式。转换涉及将程序源文本中的任何 Unicode 转义转换为 ASCII,通过添加额外的 u - 例如,\uxxxx 变为 \uuxxxx - 同时将源文本中的非 ASCII 字符转换为包含单个 u 的 Unicode 转义。

此转换后的版本对 Java 编译器来说是同样可接受的,并且表示完全相同的程序。以后可以从此 ASCII 形式还原出相同的 Unicode 源,通过将有多个 u 的转义序列转换为一个较少 u 的 Unicode 字符序列,同时将每个带有单个 u 的转义序列转换为单个相应的 Unicode 字符。

当没有合适的字体时,Java 编译器应将 \uxxxx 表示法用作输出格式,以显示 Unicode 字符。

3.4 行结束符

Java 编译器下一步通过识别行结束符来将 Unicode 输入字符序列分割成行。

LineTerminator:
    the ASCII LF character, also know as "newline"
    the ASCII CR character, also know as "return"
    the ASCII CR character followed by the ASCII LF character

InputCharacter:
    UnicodeInputCharacter but not CR or LF

行被 ASCII 字符 CR 或 LF 或 CR LF 结束。两个字符 CR 直接后跟 LF,整体被视为一个行结束符,而不是两个。

行结束符指定注释(3.7)的 // 形式的终止。

由行结束符定义的行可以确定由 Java 编译器产生的行号。

结果是一个行结束符和输入字符的序列,其是第三步标记化处理中的终端符号。

3.5 输入元素和记号

输入字符,和产生自转义处理和输入行识别的行终止符,归纳为一个输入元素序列。

Input:
    {InputElement} {Sub}

InputElement:
    WhiteSpace
    Comment
    Token

Token:
    Identifier
    Keyword
    Literal
    Separtor
    Operator

Sub:
    the ASCII SUB character, also know as "control-Z"

那些不是空格或注释的输入元素,是记号。记号是句法文法(2.3)的终端符号。

空白(3.6)和注释(3.7)可用于分隔记号,如果相邻,则可能以另一种方式标记。例如,输入中的 ASCII 字符 -和 = 可以形成操作记号 -=(3.12),仅当没有介于其中间的空白或注释时。

作为对特定操作系统兼容性的让步,ASCII SUB 字符(\u001a 或 control-Z)被忽略,如果它是转义后的输入流中的最后一个字符。

在结果输入流中考虑两个记号 x 和 y。如果 x 在 y 之前,则我们说 x 在 y 的左边,y 在 x 的右边。

3.6 空格

空格定义为 ASCII 的空格字符、水平制表符字符、换页字符和行结束符字符(3.4)。

WhiteSpace:
    the ASCII SP character, also know as "space"
    the ASCII HT character, also know as "horizontal tab"
    the ASCII FF character, also know as "form feed"
    LineTerminator

3.7 注释

有两种注释:

    /* text */

    一种传统的注释。从 ASCII 字符 /* 到 ASCII 字符 */ 之间的所有文本都被忽略(像 C 和 C++ 一样)。

    // text

    行尾注释。从 ASCII 字符 // 到行尾之间的所有文本都被忽略(像 C++ 一样)。

Comment:
    TraditionalComment
    EndOfLineComment

TraditionalComment:
    / * CommentTail

CommentTail:
    * CommentTailStar
    NotStar CommentTail

CommentTailStar:
    /
    * CommentTailStar
    NotStarNotSlash CommentTail

NotStar:
    InputCharacter but not *
    LineTerminator

NotStarNotSlash:
    InputCharacter but not * or /
    LineTerminator

EndOfLineComment:
    / / {InputCharacter}

这些产生式意味着如下所有属性:

    注释无法嵌套。

    /* 和 */ 在以 // 开始的注释中有特殊含义。

    // 在以 /* 或 /** 开始的注释中没有特殊含义。

这一词法意味着,注释无法出现在字符字面量(3.10.4)或字符串字面量(3.10.5)中。

3.8 标识符

标识符是一个不限长度的 Java 字母和 Java 数字的序列,该序列的第一个必须是 Java 字母。

Identifier:
    IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral

IdentifierChars:
    JavaLetter {JavaLetterOrDigit}

JavaLetter:
    any Unicode character that is a "Java letter"

JavaLetterOrDigit:
    any Unicode character that is a "Java letter-or-digit"

“Java letter”是一个字符,其对于方法 Character.isJavaIdentifierStart(int) 来说返回 true。

“Java letter-or-digit”是一个字符,其对于方法 Character.isJavaIdentifierPart(int) 来说返回 true。

The "Java letters" include uppercase and lowercase ASCII Latin letters A-Z (\u0041-\u005a), and a-z (\u0061-\u007a), and, for historical reasons, the ASCII underscore (_, or \u005f) and dollar sign ($, or \u0024). The $ sign should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems.

The "Java digits" include the ASCII digits 0-9 (\u0030-\u0039).

3.9 关键字

50 个由 ASCII 字符形成的字符序列被保留下来,用作关键字,不能用作标识符(3.8)。

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

虽然 true 和 false 可以作为关键字出现,但在技术上它们是 boolean 字面量(3.10.3)。类似地,虽然 null 可以作为关键字出现,但技术上它是 null 字面量(3.10.7)。

3.10 字面量

字面量是基元类型(4.2)、String 类型(4.3.3)或 null 类型(4.1)值的源代码表示。

Literal:
    IntegerLiteral
    FloatingPointLiteral
    BooleanLiteral
    CharacterLiteral
    StringLiteral
    NullLiteral

3.10.1 整数字面量

整数字面量可以用十进制(基于 10)、十六进制(基于 16)、八进制(基于 8)或二进制(基于 2)表示。

IntegerLiteral:
    DecimalIntegerLiteral
    HexIntegerLiteral
    OctatIntegerLiteral
    BinaryIntegerLiteral

DecimalIntegerLiteral:
    DecimalNumeral [IntegerTypeSuffix]

HexIntegerLiteral:
    HexNumeral [IntegerTypeSuffix]

OctatIntegerLiteral:
    OctatNumeral [IntegerTypeSuffix]

BinaryIntegerLiteral:
    BinaryNumeral [IntegerTypeSuffix]

IntegerTypeSuffix:
    (one of)
    1 L

如果用 ASCII 字符 L 或 l(ell)作为后缀,整数字面量是 long 类型;否则它是 int 类型(4.2.1)。

The suffix L is preferred, because the letter l (ell) is often hard to distinguish from the digit 1 (one).
后缀 L 优先,因为字母 l(ell)与数字 1(one)通常难以区分。

允许下划线作为表示整数的数字之间的分隔符。

在十六进制或二进制中,整数仅由 0x 或 0b 字符之后和任何类型后缀之前的数字表示。因此,下划线不可以直接出现在 0x 或 0b 后,或数值中的最后一个数字后。

在十进制或八进制字面量中,整数由类型后缀前的字面量中的所有数字表示。因此,下划线不可以出现在数值中的第一个数字前面或最后一个数字后面。下划线可以出现在八进制数值中的初始 0 后(因为 0 是一个表示整数的部分的数字)和非零十进制字面量中的初始非零数字后。

十进制数值既是单个表示整数零的 ASCII 数字 0,也是可选地后跟一个或多个从 0 到 9 的 ASCII 数字的穿插着下划线的由从 1 到 9 的 ASCII 数字组成的,表示正数。

DecimalNumeral:
    0
    NonZeroDigit [Digit]
    NonZeroDigit Underscores Digits

NonZeroDigit:
    (one of)
    1 2 3 4 5 6 7 8 9

Digits:
    Digit
    Digit [DigitAndUnderscores] Digit

Digit:
    0
    NonZeroDigit

DigitAndUnderscores:
    DigitOrUnderscore {DigitOrUnderscore}

DigitOrUnderscore:
    Digit
    _

Underscores:
    _ {_}

十进制数字由穿插着下划线的后跟一个或多个 ASCII 十进制数字的前导 ASCII 字符 0x 或 0X 组成,并且可以表示正数、零或负数。

值 10 到 15 的十六进制数字由 ASCII 字母 a 到 f 或 A 到 F 各自表示;每个用作十六进制数字的字母可以是大写或小写。

HexNumeral:
    0 x HexDigits
    0 X HexDigits

HexDigits:
    HexDigit
    HexDigit {HexDigitsAndUnderscores} HexDigit

HexDigit:
    (one of)
    0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F

HexDigitAndUnderscores:
    HexDigitOrUnderscore {HexDigitOrUnderscore}

HexDigitOrUnderscore:
    HexDigit
    _

八进制数字由后跟一个或多个从 0 到 7 的穿插着下划线的 ASCII 数字的 ASCII 数字 0 组成,并且可以表示正数、零、负数。

OctalNumeral:
    0 OctalDigits
    0 Underscores OctalDigits

OctalDigits:
    OctalDigit
    OctalDigit {OctalDigitAndUnderscores} OctalDigit

OctalDigit:
    (one of)
    0 1 2 3 4 5 6 7

OctalDigitAndUnderscores:
    OctalDigitOrUnderscore {OctalDigitOrUnderscore}

OctalDigitOrUnderscore:
    OctalDigit
    _

请注意,八进制数字总是由两个或更多个数字组成,因为单个 0 总是被认为是一个十进制数字 - 这在实际中不重要,因为数字 0、00 和 0x0 都准确表示相同的整数值。

二进制数字由后跟一个或多个穿插着下划线的 ASCII 数字 0 或 1 的前导 ASCII 字符 0b 或 0B 组成,且可以表示正数、零或负数。

BinaryNumeral:
    0 b BinaryDigits
    0 B BinaryDigits

BinaryDigits:
    BinaryDigit
    BinaryDigit [BinaryDigitAndUnderscores] BinaryDigit

BinaryDigit:
    (one of)
    0 1

BinaryDigitAndUnderscores:
    BinaryDigitOrUnderscore {BinaryDigitOrUnderscore}

BinaryDigitOrUnderscore:
    BinaryDigit
    _

类型 int 的最大的十进制字面量是 2147483648( 2的31次方)。

从 0 到 2147483648 的所有十进制字面量可以出现在一个 int 字面量可以出现的任何位置。十进制字面量 2147483648 仅可以表现为一元负号运算符-的操作数(15.15.4)。

如果十进制字面量 2147483648 出现在除了一元负号运算符的操作数以外的任何位置上,则这是一个编译时错误;或一个类型 int 的十进制字面量大于 2147483648( 231)。

类型 int 的十六进制、八进制或二进制的最大正数字面量 - 每个都表示十进制值 2147483647(2的31次方-1 )- 各自是:

    0xffff_ffff,

    0377_7777_7777,和

    0b1111_1111_1111_1111_1111_1111_1111_1111

如果一个十六进制、八进制或二进制的 int 字面量不满足 32 位,这是一个编译时错误。

类型 long 的最大十进制值是 9223372036854775808L( 2的63次方)。

从 0L 到 9223372036854775808L 的所有十进制字面量可以出现在一个 long 字面量可以出现的任何位置。十进制字面量 9223372036854775808L 仅可以表现为一元负号运算符 - 的操作数(15.15.4)。

如果十进制字面量 9223372036854775808L 出现在除了一元负号操作符的操作数以外的任何位置,则这是一个编译时错误;或如果类型 long 的十进制字面量大于 9223372036854775808L( 2的63次方)。

类型 long 的十六进制、八进制或二进制的最大负数字面量 - 每个表示十进制值 9223372036854775807L(2的63次方-1) - 各自是:

    0x7fff_ffff_ffff_ffffL,

    07_7777_7777_7777_7777L,和

    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 位,则这是编译时错误。

3.10.2 浮点数字面量

浮点数字面量具有以下部分:整数部分、十进制或十六进制点(由 ASCII 句号字符表示)、分数部分、指数和类型后缀。

浮点字面量可以以十进制(基于 10)或十六进制(基于 16)表示。

对于十进制浮点字面量,必须至少有一个数字(在整数部分或小数部分中)和十进制小数点、指数或 float 类型后缀。所有其它部分是可选的。如果存在,则指数由 ASCII 字母 e 或 E 表示,后跟一个可选的有符号整数。

对于十六进制浮点字面量,必须至少有一个数字(在整数部分或小数部分中),指数是必需的,且 float 类型后缀是可选的。指数由 ASCII 字母 p 或 P 表示,后跟一个可选的有符号整数。

允许将下划线作为那些表示整数部分的数字之间、那些表示小数部分的数字之间以及那些表示指数的数字之间的分隔符。

FloatingPointLiteral:
    DecimalFloatingPointLiteral
    HexadecimalFloatingPointLiteral

DecimalFloatingPointLiteral
    Digits . [Digits] [ExponentPart] [FloatTypeSuffix]
    . Digits [ExponentPart] [FloatTypeSuffix]
    Digits ExponentPart [FloatTypeSuffix]
    Digits [ExponentPart] FloatTypeSuffix

ExponentPart:
    ExponentIndicator SignedInteger

ExponentIndicator:
    (one of)
    e E

SignedInteger:
    [Sign] Digits

Sign:
    (one of)
    + -

FloatTypeSuffix:
    (one of)
    f F d D

HexadecimalFloatingPointLiteral:
    HexSignificand BinaryExponent [FloatTypeSuffix]

HexSignificand:
    0 x [HexDigits] . HexDigits
    0 X [HexDigits] . HexDigits

BinaryExponent:
    BinaryExponentIndicator SignedInteger

BinaryExponentIndicator:
    (one of)
    p P

如果浮点字面量有 ASCII 字母 F 或 f 作为后缀,则该浮点字面量是类型 float;否则,其类型是 double,且它可选地可以将 ASCII 字母 D 或 d 作为后缀(4.2.3)。

类型 float 和 double 的元素分别是可以使用 IEEE 754 32 位单精度和 64 位双精度二进制浮点格式表示的值。

The details of proper input conversion from a Unicode string representation of a floating-point number to the internal IEEE 754 binary floating-point representation are described for the methods valueOf of class Float and class Double of the package java.lang.

类型 float 的最大正有限字面量是 3.4028235e38f。

类型 float 的最小正有限字面量是 1.40e-45f。

类型的 double 的最大正有限字面量是 1.7976931348623157e308。

类型 double 的最小正有限非零字面量是 4.9e-324。

如果一个非零浮点字面量太大,则这是一个编译时错误,因此,在舍入转换为其内部表示形式时,它将变成 IEEE 754 无限。

程序可以通过使用常量表达式如 1f/0f 或 -1d/0d,或者使用 Float 和 Double 类的预定义的常量 POSITIVE_INFINITY 和 NEGATIVE_INFINITY 来表示无穷,而不用产生一个编译时错误。

如果一个非零浮点字面量太小,则这是一个编译时错误,因此,在舍入转换为其内部表示形式时,它将变成零。

如果一个非零浮点字面量具有一个小值,该值在舍入转换为其内部表示形式时,其将变成非零非规范化数字,则将不会出现编译时错误。

预定义的表示 Not-a-Number 值的常量在类 Float 和 Double 中定义为 Float.NaN 和 Double.NaN。

    float 字面量示例:

    1e1f    2.f    .3f    0f    3.14f    6.022137e+23f

    double 字面量示例:

    1e1    2.    .3    0.0    3.14    1e-9d    1e137

3.10.3 布尔字面量

布尔类型具有两个值,由 ASCII 字母组成的布尔字面量 true 和 false 表示。

BooleanLiteral:
    (one of)
    true false

布尔字面量总是布尔类型的(4.2.5)。

3.10.4 字符字面量

一个字符字面量总是表示为一个字符或一个转义序列(3.10.6),由 ASCII 单引号封装。(单引号或撇号字符是 \u0027。)

CharacterLiteral:
    ' SingleCharacter '
    ' EscapeSequence '

SignleCharacter:
    InputCharacter but not ' or \

转移序列的定义参见 3.10.6。

字符字面量仅可以表示 UTF-16 代码单元(3.1),即,它们被限制为值从 \u0000 到 \uffff。辅助字符要么表示为一个 char 序列中的代理对,要么表示为一个整数,这依赖于它们使用的 API。

字符字面量总是 char 类型的(4.2.1)。

对于 SingleCharacter 或 EscapeSequence 后跟的不是 ' 的字符来说,这是一个编译时错误。

对于在开始 ' 之后和关闭 ' 之前出现的行终止符(3.4)来说,这是一个编译时错误。

正如 3.4 中指示的那样,字符 CR 和 LF 从来不是 InputCharacter,每一个被识别为构成一个行指示符。

    以下是 char 字面量的示例:

        'a'

        '%'

        '\t'

        '\'

        '''

        '\u03a9'

        '\uFFFF'

        '\177'

        '™'

由于 Unicode 转义处理的非常早,因此为值为 linefeed(LF)的字符字面量写 '\u000a' 是不正确的;Unicode 转义 \u000a 被转换为转换步骤1(3.3)中的实际 linefeed,linefeed 变成步骤2(3.4)中的行终止符,字符字面量在步骤 3 中无效。反之,应该使用转义序列 '\n'(3.10.6)。类似地,为值为 carriage reture(CR)的字符字面量写 '\u000d' 是不正确的。反之,使用 '\r'。

在 C 和 C++ 中,字符字面量可能包含多于一个字符的表示形式,但此类字符字面量的值是实现定义的。在 Java 编程语言中,字符字面量始终仅表示一个字符。

3.10.5 字符串字面量

一个字符串字面量由零个或多个封闭在双引号中的字符组成。字符可以表示为转义序列(3.10.6) - 字符的一个转义序列在范围 U+0000 到 U+FFFF 中,UTF-16 代理代码单元字符的第二个转义序列在范围 U+010000 到 U+10FFFF 中。

StringLiteral:
    " {StringCharacter} "

StringCharacter:
    InputCharacter but not " or \
    EscapeSequence

转义序列的定义参见 3.10.6。

字符串字面量总是 String 类型的(4.3.3)。

对于一个出现在开始的 " 之后和关闭的匹配 " 之前的行终止符来说,这是一个编译时错误。

正如 3.4 中指示的那样,字符 CR 和 LF 从不是 InputCharacter,每一个被识别为构成一个行终止符。

长字符串字面量总是可以被分解成较短的片段,并写成使用字符串串联运算符 +(15.18.1)的(可能带圆括号)表达式。

    以下是字符串字面量的示例:

    ""                 // 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 转义处理的非常早,因此为值为 linefeed(LF)的字符字面量写 '\u000a' 是不正确的;Unicode 转义 \u000a 被转换为转换步骤 1(3.3)中的实际 linefeed,linefeed 变成步骤 2(3.4)中的行终止符,字符字面量在步骤 3 中无效。反之,应该使用转义序列 '\n'(3.10.6)。类似地,为值为 carriage reture(CR)的字符字面量写 '\u000d' 是不正确的。反之,使用 '\r'。最终,不可能为了包含一个双引号(")的字符串字面量而写 "\u0022"。

字符串字面量是类 String(4.3.1,4.3.3)的一个实例的一个引用。

此外,字符串字面量总是引用类 String 的相同实例。这是因为字符串字面量 - 或者笼统地说,值为字符串的常量表达式(15.28) - 是被“拘留”的,以便共享唯一的实例,使用方法 String.intern。

    这个示例展示了六点:

        同一包(7(Packages))下同一类(8(Classes))中的的字面量字符串表示到同一 String 对象的引用(4.3.1)。

        同一包下不同类中的字面量字符串表示到同一 String 对象的引用。

        不同包下不同类中的字面量字符串同样表示到同一 String 对象的引用。

        由常量表达式(15.28)计算的字符串在编译时计算出,然后将它们视为字面量。

        由串联运算符计算的字符串在运行时新创建,并因此不同。

        显式拘束计算出的字符串的结果与任何预先存在的具有相同内容的字面量字符串是同一字符串。

3.10.6 字符和字符串字面量的转义序列

字符字面量(3.10.4)和字符串字面量(3.10.5)中的字符和字符串的转义序列允许在不使用 Unicode 转义的情况下的某些非图形字符的表示形式,以及单引号、双引号和反斜线字符。

EscapeSequence:
    \ b (backspace BS, Unicode \u0008)
    \ t (horizontal tab HT, Unicode \u0009)
    \ n (linefeed LF, Unicode \u000a)
    \ f (form feed FF, Unicode \u000c)
    \ r (carriage return CR, Unicode \u000d)
    \ " (double quote ", Unicode \u0022)
    \ ' (single quote ', Unicode \u0027)
    \ \ (backslash , Unicode \u005c)
    OctalEscape (octal value, Unicode \u0000 to \u00ff)

OctalEscape:
    \ OctalDigit
    \ OctalDigit OctalDigit
    \ ZeroToThree OctalDigit OctalDigit

OctalDigit:
    (one of)
    0 1 2 3 4 5 6 7

ZeroToThree:
    (one of)
    0 1 2 3

以上 OctalDigit 产生式来自 3.10.1。

如果一个转义序列中的反斜线后面的字符不是 ASCII b、t、n、f、r、"、'、\、0、1、2、3、4、5、6 或者 7,则这是一个编译时错误。Unicode 转义 \u 处理的更早(3.3)。

八进制转义为了提供与 C 的兼容性,仅可以表示 \u0000 到 \u00FF 的 Unicode 值,所以通常首选 Unicode 转义。

3.10.7 Null 字面量

null 类型有一个值,null 引用,由 null 字面量 null 表示,其由 ASCII 字符组成。

NullLiteral:
    null

null 字面量总是 null 类型的(4.1)。

3.11. 分隔符

十二个由 ASCII 字符组成的标记是分隔符(标点符号)。

Separator:
    (one of)

    (    )    {    }    [    ]    ;    ,    .    ...    @    ::

3.12. 运算符

38个由 ASCII 字符组成的标记是运算符。

Operator:
    (one of)

    =    >    <    !    ~    ?    :    ->
    ==    >=    <=    !=    &&    ||    ++    --
    +    -        /    &    |    ^    %    <<    >>    >>>
    +=    -=    
=    /=    &=    |=    ^=    %=    <<=    >>=    >>>=