Java语言规范第三章-词法(Java Language Specification – Chapter3 Lexical)
UnicodeInputCharacter:
UnicodeEscape
RawInputCharacter
UnicodeEscape:
/ UnicodeMarker HexDigit HexDigit HexDigit HexDigit
UnicodeMarker:
u
UnicodeMarker u
RawInputCharacter:
any Unicode character
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
必须计算有多少个连续的/,与非/或者输入流的起始相分隔,如果连续的/的个数为奇数,那么/作为Unicode的转义字符,否则不作为Unicode的转义字符。例如"//u2297=/u2297"
的输出为
"//u2297=
"
(/u2297
的
Unicode
编码字符为
" ")。
如果合法(连续的奇数个/)的Unicode转义字符后面的字符不是u,那么作为原始字符来处理。如果后面的字符是1个或者多个u,而且字符u后面不是四位16进制数,那么将发生编译时错误。
进行Unicode转义时,并不进行二次转义。例如原始输入/u005cu005a
转义后的输出为
/u005a
,虽然
/005c
是
Unicode
字符
/
,而
/u005a
是字符
Z
,但是
Unicode
转义时不进行二次转义。
LineTerminator:
the ASCII LF
character, also known as "newline"
the ASCII CR
character, also known 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
被作为一个行结束符,而不是两个。
Input:
InputElementsopt Subopt
InputElements:
InputElement
InputElements InputElement
InputElement:
WhiteSpace
Comment
Token
Token:
Identifier
Keyword
Literal
Separator
Operator
Sub:
the ASCII SUB character, also known as "control-Z"
为了兼容某些特定的系统,作为一个特例情况,
ASCII
的
SUB
字符
(/u001a
或者
CTRL+Z)
如果出现在输入流的末尾,那么该字符被忽略。
WhiteSpace:
the ASCII SP character, also known as "space"
the ASCII HT character, also known as "horizontal tab"
the ASCII FF character, also known as "form feed"
LineTerminator
Identifier:
IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral
IdentifierChars:
JavaLetter
IdentifierChars JavaLetterOrDigit
JavaLetter:
any Unicode character that is a Java letter (see below)
JavaLetterOrDigit:
any Unicode character that is a Java letter-or-digit (see below)
两个标识符相同当且仅当它们的每个字符都具有相同的
Unicode
字符。
两个具有相同表现形式可能是不同的。例如下面的这些标识符是不同的。
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)
组成的,但是他们是不同的标识符。
CharacterLiteral:
' SingleCharacter '
' EscapeSequence '
SingleCharacter:
InputCharacter but not ' or /
字符CR和LF不再属于InputCharacter;因为它们在之前的阶段已经被认为是LineTerminator。
如果SingleCharacter或者EscapeSequence后面跟的字符不是单引号(’)的话,将导致编译时错误。
如果行结束符出现在起始单引号和结束单引号之间,将导致编译时错误。
由于Unicode转义已经在之前的阶段中被处理,所以下面的字符是不正确的/u000a(LF),/u000d(CR),因为他们在Unicode转义阶段被转义为实际的linefeed以及carriage return,而在行结束符阶段被看作是行结束符号。所以应该使用/n和/r来替代。
StringLiteral:
" StringCharactersopt "
StringCharacters:
StringCharacter
StringCharacters StringCharacter
StringCharacter:
InputCharacter but not " or /
EscapeSequence
字符CR和LF不再属于InputCharacter;因为它们在之前的阶段已经被认为是LineTerminator。
如果SingleCharacter或者EscapeSequence后面跟的字符不是单引号(’)的话,将导致编译时错误。
如果行结束符出现在起始单引号和结束单引号之间,将导致编译时错误。
由于Unicode转义已经在之前的阶段中被处理,所以下面的字符是不正确的/u000a(LF),/u000d(CR),因为他们在Unicode转义阶段被转义为实际的linefeed以及carriage return,而在行结束符阶段被看作是行结束符号。所以应该使用/n和/r来替代。
package org.jff.jls.ch2;
public class StringIntern {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");//true
System.out.print((Other.HELLO == hello) + " ");//true
System.out.print((org.jff.jls.ch2.other.Other.HELLO == hello) + " ");//true
System.out.print((hello == ("Hel" + "lo")) + " ");//true
System.out.print((hello == ("Hel" + lo)) + " ");//false
System.out.println(hello == ("Hel" + lo).intern());//true
}
}
package org.jff.jls.ch2.other;
public class Other {
public static String HELLO = "Hello";
}
相同类中的字符串引用相同的String对象。
相同包中的不同类的字符串引用相同的String对象。
不同包中的不同类的字符串用用相同的对象。
常量表达式计算出来的字符串发生在编译时,因此作为字符串处理。
通过连接计算出来的字符串发生在运行时,作为新建的对象,因此是不相同的。