第3章 字句構造

目次

3.1 ユニコード
3.2 字句翻訳
3.3 Unicodeエスケープ
3.4 明細ターミネータ
3.5 入力要素とトークン
3.6 ホワイトスペース
3.7 コメント
3.8 識別子
3.9 キーワード
3.1 リテラル
3.1 整数リテラル
3.1 浮動小数点リテラル
3.1 ブール・リテラル
3.1 文字リテラル
3.1 文字列リテラル
3.1 テキスト・ブロック
3.1 エスケープ・シーケンス
3.1 Nullリテラル
3.11 セパレータ
3.12 演算子

この章では、Javaプログラミング言語の字句構造について説明します。

プログラムはUnicode(§3.1)で書かれていますが、字句翻訳が提供されています(§3.2)。Unicodeエスケープ(§3.3)を使用して、ASCII文字のみを使用するUnicode文字を含めることができます。 一貫した行番号を維持しながら、既存のホストシステムのさまざまな規則をサポートするために、行端子(§3.4)が定義されています。

字句変換によって生成されるUnicode文字は、一連の入力要素(§3.5)、空白(§3.6)、コメント(§3.7)およびトークンに縮小されます。 トークンは、構文文法の識別子(§3.8)、キーワード(§3.9)、リテラル(§3.10)、セパレータ(§3.11)、および演算子(§3.12)です。

3.1.  Unicode

プログラムは、Unicode文字セット(§1.7)を使用して記述されます。 この文字セットとそれに関連付けられた文字エンコーディングに関する情報は、https://www.unicode.org/にあります。

Java SEプラットフォームでは、Unicode Standardが展開されるたびに追跡されます。 特定のリリースで使用されるUnicodeの正確なバージョンは、クラスCharacterのドキュメントで指定されています。

Unicode Standardは、本来は固定幅の16ビット文字エンコーディングとして設計されました。 その後、16ビット以上の表現を必要とする文字を許容するように変更されています。 16進数のU+n表記を使用して、有効なコード・ポイントの範囲がU+0000からU+10FFFFになりました。 コード・ポイントがU+FFFFより大きい文字は、補助文字と呼ばれます。 16ビット単位のみを使用して文字の範囲全体を表すために、Unicode StandardではUTF-16というエンコーディングを定義しています。 このエンコーディングでは、補足文字は16ビット・コード・ユニットのペアとして表現され、最初のコード・ユニットは上位サロゲート範囲(U+D800からU+DBFF)から、2番目のコード・ユニットは下位サロゲート範囲(U+DC00からU+DFFF)から取得されます。 U+0000からU+FFFFの範囲の文字の場合、コード・ポイントとUTF-16コード・ユニットの値は同じです。

Javaプログラミング言語は、UTF-16エンコーディングを使用した16ビット・コード単位のシーケンスでテキストを表します。

Java SEプラットフォームの一部のAPIは、主にCharacterクラスにあり、32ビット整数を使用してコード・ポイントを個々のエンティティとして表します。 Java SEプラットフォームには、16ビット表現と32ビット表現を変換するメソッドが用意されています。

この仕様では、表現が関連するコード・ポイントおよびUTF-16コード・ユニットという用語と、表現がディスカッションに関連しない一般的な用語文字を使用します。

コメント(§3.7)、識別子(§3.8)、および文字リテラル、文字列リテラル、およびテキストブロックの内容(§3.10.4§3.10.5§3.10.6)を除き、プログラム内のすべての入力要素(§3.5)はASCII文字(または、ASCII文字になるUnicodeエスケープ(§3.3)からのみ形成されます。

ASCII (ANSI X3.4)は、情報交換用米国標準コード(American Standard Code for Information Interchange)です。 Unicode UTF-16エンコーディングの最初の128文字はASCII文字です。

3.2.  字句変換

RAW Unicode文字ストリームは、次の3つの字句変換ステップを順番に適用することで、トークンのシーケンスに変換されます。

  1. Unicode文字のRAWストリーム内のUnicodeエスケープ(§3.3)から対応するUnicode文字への変換。 \\uxxxx形式のUnicodeエスケープ(xxxxは16進値)は、エンコーディングがxxxxのUTF-16コード・ユニットを表します。 この変換ステップによって、ASCII文字のみを使用してプログラムを表現できます。

  2. ステップ1の結果のUnicodeストリームから、入力文字および行終了文字のストリームへの変換(§3.4)。

  3. ステップ2で得られた入力文字と行終了文字のストリームを、空白(§3.6)とコメント(§3.7)の後に破棄される一連の入力要素(§3.5)に変換すると、構文文法(§2.3)の終端記号であるトークンが構成されます。

結果が最終的に正しいプログラムを作成せず、別の字句変換を行う場合でも、各ステップで可能なかぎり長い変換が使用されます。 より詳細な翻訳が必要な状況を考慮する例外は2つあります。ステップ1では、連続する\\文字の処理(§3.3)、ステップ3では、コンテキスト・キーワードと隣接する>文字の処理(§3.5)です。

入力文字a--bは、文法的に正しいプログラムの一部ではないa--およびbとしてトークン化されます。これは、トークン化a--bが文法的に正しいプログラムの一部である場合でも同様です。 トークン化a--およびbは、入力文字a- -bを使用して実現できます(2つの-文字の間にASCII SP文字を使用)。

raw入力\\ሴは、\\文字に変換され、(可能なかぎり長いルールに従って)\\u1234形式のUnicodeエスケープであると想定されます。 実際、先頭の\\文字を使用すると、このRAW入力は、\\ \\ u 1 2 3 4という7つの異なる文字に変換されます。

3.3. Unicodeエスケープ

Javaプログラミング言語(「Javaコンパイラ」)のコンパイラは、最初にUnicodeエスケープをそのRAW入力で認識し、ASCII文字\\uの後に4桁の16進数が、示された16進値のUTF-16コード単位(§3.1)を示すRAW入力文字に変換しています。 1つのUnicodeエスケープは、U+0000からU+FFFFの範囲の文字を表すことができ、U+010000からU+10FFFFの範囲の補助文字を表すには、2つの連続するUnicodeエスケープが必要です。 コンパイラのraw入力内のほかのすべての文字はraw入力文字として認識され、そのまま渡されます。

この変換ステップでは、Unicode入力文字のシーケンスが生成され、そのすべてがRAW入力文字になります(UnicodeエスケープがRAW入力文字に縮小されている場合)。

UnicodeInputCharacter:
UnicodeMarker:
u {u}
HexDigit:
(いずれか)
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
RawInputCharacter:
UTF-16で表現可能な任意のUnicode文字

ここでの\\uおよび16進数はすべてASCII文字です。

コンパイラのRAW入力のASCII \\文字をRawInputCharacterまたはUnicodeEscape\\ (その後にASCII uが続く)に減らすことができるため、UnicodeInputCharacterの本番環境はあいまいです。 あいまいさを回避するために、コンパイラのRAW入力のASCII \\文字ごとに、入力処理では、この変換ステップの結果である最新のRAW入力文字を考慮する必要があります。

  • 結果内の最新のRAW入力文字自体がコンパイラのRAW入力内のUnicodeエスケープから変換された場合、ASCII \\文字はUnicodeエスケープを開始できます。

    たとえば、結果の最新のRAW入力文字がRAW入力のUnicodeエスケープ\\u005cから発生したバックスラッシュである場合、RAW入力の次のASCII \\文字は、別のUnicodeエスケープを開始する対象となります。

  • それ以外の場合は、結果に生の入力文字として連続して出現したバックスラッシュの数、バックスラッシュ以外の文字または結果の先頭に戻る数を考慮してください。 (このようなバックスラッシュがコンパイラのRAW入力のASCII \\文字またはコンパイラのRAW入力のUnicodeエスケープ\\u005cから発生したかどうかは重要ではありません。) この数値が偶数の場合、ASCIIの\\文字はUnicodeエスケープを開始できます。数値が奇数の場合、ASCIIの\\文字はUnicodeエスケープを開始できません。

    たとえば、RAW入力の"\\™=\\u2122"は11文字の" \\ \\ u 2 1 2 2 = ™ "になります。これは、RAW入力の2番目のASCII \\文字がUnicodeエスケープの開始に適格ではなく、3番目のASCII \\文字が適格であり、\\u2122が文字のUnicodeエンコーディングであるためです。

適格な\\の後にuがない場合は、RawInputCharacterとして扱われ、エスケープされたUnicodeストリームの一部のままになります。

適格な\\の後にuまたは複数のuが続いており、最後のuの後に4桁の16進数が続いていない場合は、コンパイル時にエラーが発生します。

Unicodeエスケープによって生成される文字は、それ以上のUnicodeエスケープには含まれません。

たとえば、RAW入力\\u005cu005aは、005cがバックスラッシュのUnicode値であるため、6文字の\\ u 0 0 5 aになります。 Unicodeエスケープ\\u005cの処理によって生じたバックスラッシュは、それ以上のUnicodeエスケープの開始として解釈されないため、文字ZはUnicode値005aになりません。

\\u005cu005aを文字列リテラルに書き込んで、6文字の\\ u 0 0 5 aを示すことはできません。 これは、変換の結果の最初の2文字である\\およびuが、文字列リテラルで不正なエスケープ・シーケンス(§3.10.7)として解釈されるためです。

幸いなことに、連続するバックスラッシュ文字に関するルールは、プログラマが文字列リテラル内のUnicodeエスケープを示すRAW入力を作成するのに役立ちます。 文字列リテラル内の6文字の\\ u 0 0 5 aを示すには、"\\Z is Z"など、既存の\\の隣に別の\\を配置する必要があります。 これは、RAW入力\\Zの2番目の\\がUnicodeエスケープを開始できないため、最初の\\および2番目の\\は、次の5文字のu 0 0 5 aと同様にRAW入力文字として保持されます。 その後、2つの\\文字が文字列リテラルでバックスラッシュのエスケープ・シーケンスとして解釈され、必要な6文字の\\ u 0 0 5 aを含む文字列になります。 An exception mapping did not successfully produce and processed a response. Logging the exception propagated to the default exception mapper. (このルールでは、最初のUnicodeエスケープが生の入力文字\に変換されても、2番目のUnicodeエスケープが別の生の入力文字\に変換されることを防ぐことができないため、\u005c\u005c\\に変換されます。)

このルールにより、プログラマは文字列リテラル内のエスケープ・シーケンスを示すRAW入力を作成することもできます。 たとえば、RAW入力\\\\nでは、最初の\\および2番目の\\はRAW入力文字として保持され、3番目の\\ではUnicodeエスケープを開始できるため、\\u006eはRAW入力文字nに変換されるため、3文字\\ \\ nになります。 その後、3文字の\\ \\ nは文字列リテラルで\\ nとして解釈され、これはラインフィードのエスケープ・シーケンスを示します。 (各Unicodeエスケープ\\u005cはRAW入力文字\\に変換されるため、残りのRAW入力\\u006eの前に偶数のバックスラッシュが付けられ、nのUnicodeエスケープとして処理されるため、\\\\n\\u005c\\u005c\\u006eとして記述できます。)

Javaプログラミング言語は、Unicodeで書かれたプログラムをASCIIに変換する標準的な方法を指定します。この方法は、プログラムをASCIIベースのツールで処理できる形式に変更します。 変換では、プログラムのソース・テキスト内のUnicodeエスケープをASCIIに変換し、追加のuを追加します。たとえば、\\uxxxx\\uuxxxxになります。同時に、ソース・テキスト内の非ASCII文字を、それぞれ1つのuを含むUnicodeエスケープに変換します。

この変換されたバージョンは、Javaコンパイラでも同様に受け入れられ、まったく同じプログラムを表します。 正確なUnicodeソースは、複数のuが存在する各エスケープ・シーケンスを、1つ少ないuのUnicode文字のシーケンスに変換し、同時に単一のuを持つ各エスケープ・シーケンスを対応する単一のUnicode文字に変換することで、このASCII形式からリストアできます。

Javaコンパイラは、適切なフォントが使用できない場合にUnicode文字を表示するために、\\uxxxx表記を出力形式として使用する必要があります。

3.4. 明細ターミネータ

Javaコンパイラは次に、行終了文字を認識して、Unicode入力文字のシーケンスを1行に分割します。

LineTerminator:
ASCII LF文字(「復帰」とも呼ばれる)
ASCII CR文字(「復帰」とも呼ばれる)
ASCII CR文字のあとにASCII LF文字が続く
InputCharacter:
UnicodeInputCharacter ただしCRまたはLFは除く

行は、ASCII文字CR、LF、またはCR LFで終了します。 LFの直後に続く2文字のCRは、2つではなく1行端子としてカウントされます。

行末記号は、コメントの//形式の終了を指定します(§3.7)。

行末記号で定義される行は、Javaコンパイラによって生成される行番号を決定できます。

結果は、トークン化プロセスの3番目のステップの終端記号である行の終端文字および入力文字のシーケンスです。

3.5.  入力要素およびトークン

Unicodeエスケープ処理(§3.3)から入力行認識(§3.4)に至る入力文字と行終了文字は、入力要素のシーケンスに縮小されます。

入力:
補助:
ASCII SUB文字、別名はcontrol-Z

空白やコメント以外の入力要素は、トークンです。 トークンは構文文法(§2.3)の終端記号です。

ホワイト・スペース(§3.6)とコメント(§3.7)は、隣接している場合には別の方法でトークン化される可能性があるトークンを分離するために役立つ。

たとえば、入力文字-および=が演算子トークン-= (§3.12)を形成できるのは、空白やコメントが介在していない場合のみです。 別の例として、10個の入力文字staticvoidは単一の識別子トークンを形成し、11個の入力文字static void (cvの間のASCII SP文字)は、空白で区切られたキーワード・トークンのペアstaticvoidを形成します。

特定のオペレーティング・システムとの互換性を確保するための特別な譲歩として、ASCII SUB文字(\\u001aまたはcontrol-Z)は、エスケープされた入力ストリームの最後の文字である場合は無視されます。

Inputの生成はあいまいです。つまり、入力文字のシーケンスでは、入力文字を入力要素に減らす(つまり、入力文字をトークン化する)複数の方法があります。 あいまいさは次のように解決されます。

  • 識別子トークンまたはリテラル・トークンのいずれかに還元できる入力文字のシーケンスは、常にリテラル・トークンに還元されます。

  • 識別子トークンまたは予約済キーワード・トークン(§3.9)のいずれかに減らすことができる一連の入力文字は、常に予約済キーワード・トークンに縮小されます。

  • コンテキスト・キーワード・トークンまたは他の(非キーワード)トークンに減らすことができる入力文字のシーケンスは、§3.9で指定されているように、コンテキストに従って減少します。

  • 入力文字>が型コンテキスト(§4.11)に含まれる場合、つまり、構文文法におけるTypeまたはUnannTypeの一部として(§4.1§8.3)、別の演算子を形成するために隣接する>文字と組み合せることができる場合でも、常に数値比較演算子>に縮小されます。

    >文字に対するこのルールがない場合、List<List<String>>などの型内の2つの連続する>カッコは、符号付き右シフト演算子>>としてトークン化され、List<List<List<String>>>などの型内の3つの連続する>カッコは符号なし右シフト演算子>>>としてトークン化されます。 さらに悪いことに、>>>および>>>トークンの様々な組合せが>>>>文字を表す可能性があるため、List<List<List<List<String>>>>などの型で連続する4つ以上の>カッコのトークン化があいまいになります。

結果の入力ストリームの2つのトークンxおよびyについて考えてみます。 xyの前にあり、xy左側で、yx右側であるとします。

たとえば、次の簡単なコードでは、

class Empty {
}

}トークンは、{トークンの右側にありますが、この2次元表現では、下方向、および{トークンの左側に表示されます。 左と右という言葉の使用に関するこの取り決めにより、たとえば、バイナリ演算子の右側のオペランドや代入の左側と言い表すことができます。

3.6.  空白

空白は、ASCIIスペース文字、水平タブ文字、フォーム・フィード文字および行終了文字(§3.4)として定義されます。

WhiteSpace:
ASCII SP文字(スペースとも呼ばれる)
ASCII HT文字(水平タブとも呼ばれる)
ASCII FF文字(フォーム・フィードとも呼ばれる)
LineTerminator

3.7. コメント

次の2種類のコメントがあります。

  • /* テキスト */

    従来のコメント: ASCII文字/*からASCII文字*/までのすべてのテキストは無視されます(CおよびC++の場合と同様)。

  • // テキスト

    end-of-lineコメント: ASCII文字//から行の末尾までのすべてのテキストは無視されます(C++など)。

TraditionalComment:
NotStar:
NotStarNotSlash:
EndOfLineComment:

これらのプロダクションは、次のプロパティをすべて意味します。

  • コメントはネストしません。

  • /*および*/は、//で始まるコメントでは特別な意味を持ちません。

  • //は、/*または/**で始まるコメントでは特別な意味を持ちません。

その結果、次のテキストは1つの完全なコメントになります。

/* this comment /* // /** ends here: */

字句文法は、文字リテラル、文字列リテラルまたはテキスト・ブロック(§3.10.4§3.10.5§3.10.6)内にコメントがないことを意味します。

3.8. 識別子

識別子は、Java文字およびJava桁の無制限の順序で、最初の文字はJava文字である必要があります。

識別子:
IdentifierChars ではなく ReservedKeyword または BooleanLiteral または NullLiteral
IdentifierChars:
JavaLetter:
「Javaの文字」である任意のUnicode文字
JavaLetterOrDigit:
「Javaの文字または数字」である任意のUnicode文字

Java文字は、メソッドCharacter.isJavaIdentifierStart(int)がtrueを返す文字です。

Java文字または数字は、メソッドCharacter.isJavaIdentifierPart(int)がtrueを返す文字です。

Java文字には、大文字と小文字のASCIIラテン文字A-Z (\\u0041-\\u005a)およびa-z (\\u0061-\\u007a)が含まれ、過去の理由から、ASCIIドル記号($または\\u0024)およびアンダースコア(_または\\u005f)が含まれます。 ドル記号は、正式に生成されたソース・コードでのみ使用するか、レガシー・システムの既存の名前にアクセスする場合はほとんど使用しないでください。 アンダースコアは2文字以上の識別子で使用できますが、キーワードであるため、1文字の識別子として使用することはできません。

Java桁には、ASCII桁の0-9 (\\u0030-\\u0039)が含まれます。

Unicode文字セット全体から文字や数字を取得することができます。Unicode文字セットでは、中国語、日本語および韓国語の大きなセットを含め、現在で使用するスクリプトの最も多くをサポートしています。 このため、プログラマはネイティブ言語で記述されたプログラム内で識別子を使用できます。

無視可能な文字を無視した後に、文字または数字ごとに同じUnicode文字が識別子に含まれる場合にのみ、2つの識別子は同じになります。 無視可能な文字は、メソッド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 Standardの第3.11項、"正規化フォーム"を参照してください。

識別子の例を次に示します:

  • String

  • i3

  • αρετη

  • MAX_VALUE

  • isLetterOrDigit

識別子は、トークン化の規則(§3.5)により、予約されたキーワード(§3.9)、ブール・リテラル(§3.10.3)またはnullリテラル(§3.10.8)と同じスペル(Unicode文字シーケンス)を持つことはありません。 ただし、プログラム内でのシーケンスの表示場所によって、入力文字列を識別子またはコンテキスト・キーワードのどちらでトークン化するかは、プログラム内の順序の表示場所によって決まるため、識別子がコンテキスト・キーワードと同じスペルになる場合があります。

コンテキスト・キーワードの認識を容易にするために、構文文法(§2.3)では、識別子のサブセットのみを受け入れるように本番を定義することで、特定の識別子を許可しない場合があります。 サブセットは、次のとおりです。

TypeIdentifier:
permitsrecordsealedvarまたはyieldではない識別子
UnqualifiedMethodIdentifier:
yieldではなく識別子

TypeIdentifierは、クラス、インタフェースおよび型パラメータの宣言(§8.1§9.1§4.4)および型を参照するとき(§6.5)で使用されます。 たとえば、クラスの名前はTypeIdentifierである必要があるため、permitsrecordsealedvarまたはyieldという名前のクラスを宣言することは不正です。

UnqualifiedMethodIdentifierは、メソッド呼出し式が単純名(§6.5.7.1)でメソッドを参照する場合に使用されます。 yieldという用語はUnqualifiedMethodIdentifierから除外されるため、yieldという名前のメソッドの呼出しは修飾される必要があるため、yield文(§14.21)と呼出しを区別します。

3.9. キーワード

ASCII文字から形成される51文字シーケンスは、キーワードとして使用するために予約されており、識別子として使用することはできません(§3.8)。 その他の同じくASCII文字で構成された17個の文字シーケンスは、出現するコンテキストによっては、キーワードや別のトークンとして解釈される可能性があります。

ReservedKeyword:
(次のうちの1つ)
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
_ (underscore)
ContextualKeyword:
(次のうちの1つ)
exports      opens      requires     uses   yield
module       permits    sealed       var         
non-sealed   provides   to           when        
open         record     transitive   with        

キーワードconstおよびgotoは、現在使用されていなくても予約されています。 これによって、これらのC++キーワードがプログラム内に不適切に表示されると、Javaコンパイラがより適切なエラー・メッセージを生成できるようになります。

キーワードstrictfpは廃止されているため、新しいコードでは使用しないでください。

キーワード_ (アンダースコア)は、識別子のかわりに特定の宣言で使用できます(§6.1)。

trueおよびfalseは、キーワードではなくブール・リテラル(§3.10.3)です。

nullはキーワードではなく、NULLリテラル(§3.10.8)です。

入力要素への入力文字の削減(§3.5)では、次の両方の条件が保持されている場合にのみ、コンテキスト・キーワードと一致する入力文字のシーケンスがコンテキスト・キーワードに縮小されます。

  1. シーケンスは、次のように構文文法(§2.3)の適切なコンテキストで指定された端末として認識されます。

    • moduleの場合、SingleModuleImportDeclaration (§7.5.5)またはModuleDeclaration (§7.7)で端末として認識される場合。

    • openの場合、ModuleDeclaration (§7.7)で端末として認識された場合。

    • exportsopensprovidesrequirestousesおよびwithの場合は、ModuleDirectiveで端末として認識されます。

    • transitiveの場合、RequiresModifierで端末として認識されます。

      たとえば、順序requires transitive ;を認識してもRequiresModifierは使用されないため、ここではtransitiveという用語がコンテキスト・キーワードではなく識別子に縮小されます。

    • varの場合、LocalVariableType (§14.4)またはLambdaParameterType (§15.27.1)で端末として認識される場合。

      他のコンテキストでは、varTypeIdentifier (§3.8)ではないため、識別子としてvarを使用しようとするとエラーが発生します。

    • yieldの場合、YieldStatement (§14.21)で端末として認識された場合。

      他のコンテキストでは、yieldを識別子として使用しようとすると、yieldTypeIdentifierでもUnqualifiedMethodIdentifierでもないため、エラーが発生します。

    • recordの場合、RecordDeclaration (§8.10)で端末として認識された場合。

    • non-sealedpermitsおよびsealedの場合、NormalClassDeclaration (§8.1)またはNormalInterfaceDeclaration (§9.1)で端末として認識された場合。

    • whenの場合、Guard (§14.11.1)で端末として認識された場合。

  2. 順序は、JavaLetterOrDigitに一致する入力文字の直前または直後のいずれにもなりません。

一般に、ソース・コードの空白を誤って省略すると、「可能な限り長い変換」規則(§3.2)により、一連の入力文字が識別子としてトークン化されます。 たとえば、12個の入力文字p u b l i c s t a t i cのシーケンスは、予約済キーワードpublicおよびstaticではなく、常に識別子publicstaticとしてトークン化されます。 2つのトークンを使用する場合は、空白またはコメントで区切る必要があります。

前述のルールは、"可能な限り長い翻訳"ルールと連携して動作し、コンテキスト・キーワードが表示されるコンテキストで直感的な結果を生成します。 たとえば、11個の入力文字v a r f i l e n a m eのシーケンスは通常、識別子varfilenameとしてトークン化されますが、ローカル変数宣言では、前述のルールの最初の条件によって、最初の3つの入力文字がコンテキスト・キーワードvarとして仮に認識されます。 ただし、次の8つの入力文字を識別子filenameとして認識することで、シーケンス内の空白がないことを見落とすのはわかりにくいでしょう。 (これは、順序が異なるコンテキストで異なるトークン化を受けていることを意味: ほとんどのコンテキストでは識別子ですが、ローカル変数宣言ではコンテキスト・キーワードと識別子です。) したがって、2番目の条件では、入力文字fの直後の文字がJavaLetterOrDigitであるという理由で、コンテキスト・キーワードvarが認識されません。 したがって、順序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の3つのトークンに変換されますが、最初の条件が保持される通常のクラス宣言では、最初の10個の入力文字がコンテキスト・キーワードnon-sealedとして暫定的に認識されます。 順序を3つの非キーワード・トークンではなく2つのキーワード・トークン(non-sealedおよびclass)に変換しないようにし、classの前に空白を省略してもプログラマに報酬を与えないようにするには、2番目の条件によってコンテキスト・キーワードが認識されません。 したがって、順序n o n - s e a l e d c l a s sは、クラス宣言で3つのトークンとしてトークン化されます。

前述のルールでは、最初の条件は構文文法の詳細に依存しますが、Javaプログラミング言語のコンパイラは、入力プログラムを完全に解析せずにルールを実装できます。 たとえば、コンテキスト・キーワードの有効な使用がキーワードとしてトークン化され、識別子の有効な使用が識別子としてトークン化されることがヒューリスティックで保証されているかぎり、ヒューリスティックを使用してトークナイザのコンテキスト状態を追跡できます。 または、コンパイラは常にコンテキスト・キーワードを識別子としてトークン化し、これらの識別子の特殊な使用を認識するために後のフェーズに残すことができます。

3.10.  リテラル

リテラルは、プリミティブ型の値(§4.2)、String型(§4.3.3)、またはnull型(§4.1)のソース・コード表現です。

3.10.1.  整数リテラル

整数リテラルは、10進数(ベース10)、16進数(ベース16)、8進数(ベース8)または2進数(ベース2)で表すことができます。

DecimalIntegerLiteral:
HexIntegerLiteral:
OctalIntegerLiteral:
BinaryIntegerLiteral:
IntegerTypeSuffix:
(いずれか)
l L

整数リテラルは、ASCII文字Lまたはl (ell)で接尾辞が付けられている場合はlong型、そうでない場合はint型(§4.2.1)です。

文字l (ell)は数字1 (one)と区別しにくいことが多いため、接尾辞Lが推奨されます。

アンダースコアは、整数を示す数字間のセパレータとして使用できます。

16進リテラルまたはバイナリ・リテラルでは、整数は0xまたは0b文字の後の数字と、任意の型の接尾辞の前の数字によってのみ示されます。 したがって、アンダースコアは、0xまたは0bの直後、または数字の最後の数字の後に指定できません。

10進リテラルまたは8進リテラルでは、整数は、任意の型の接尾辞の前にリテラル内のすべての桁で示されます。 したがって、アンダースコアは、最初の数字の前や数字の最後の数字の後には表示されません。 アンダースコアは、最初の0の8進数(0は整数の一部を示す数字であるため)の後、およびゼロ以外の10進リテラルの最初の0以外の桁の後に指定できます。

10進数値は、整数0を表す単一のASCII数字0であるか、または1から9までのASCII数字で構成され、オプションで、0から9までの1つ以上のASCII数字がアンダースコアと交差し、正の整数を表します。

NonZeroDigit:
(いずれか)
1 2 3 4 5 6 7 8 9
Digit:
DigitsAndUnderscores:
DigitOrUnderscore:
桁数
_
アンダースコア:
_ {_}

16進数値は、先行するASCII文字0xまたは0Xと、その後にアンダースコアにまたがる1つ以上のASCII 16進数で構成され、正、ゼロまたは負の整数を表すことができます。

値が10から15の16進数は、それぞれASCII文字aからf、またはAからFで表されます。16進数として使用される各文字は、大文字または小文字にすることができます。

HexNumeral:
HexDigit:
(いずれか)
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
HexDigitsAndUnderscores:
HexDigitOrUnderscore:

上記の HexDigit本番は、§3.3に基づいています。

8進数値は、ASCII数字の0の後に1つ以上のASCII数字の0から7がアンダースコアに割り込まれ、正、ゼロまたは負の整数を表すことができます。

OctalDigit:
(いずれか)
0 1 2 3 4 5 6 7
OctalDigitsAndUnderscores:
OctalDigitOrUnderscore:

8進数は常に2桁以上の数字で構成されていることに注意してください。これは、0のみは常に10進数とみなされるためです。実際には重要ではないため、000および0x0の数値はすべてまったく同じ整数値を表します。

2進数値は、先行するASCII文字の0bまたは0Bと、その後にアンダースコアと交差する1つ以上のASCII数字の0または1で構成され、正、ゼロまたは負の整数を表すことができます。

BinaryNumeral:
BinaryDigit:
(いずれか)
0 1
BinaryDigitsAndUnderscores:
BinaryDigitOrUnderscore:

int型の最大の10進リテラルは、2147483648 (231)です。

0から2147483647までのすべての10進リテラルは、intリテラルが存在する任意の場所に存在できます。 小数リテラル2147483648は、単項マイナス演算子-のオペランドとしてのみ指定できます(§15.15.4)。

10進リテラル2147483648が単項マイナス演算子のオペランド以外の場所にある場合、またはint型の10進リテラルが2147483648 (231)より大きい場合、コンパイル時にエラーが発生します。

int型の最大正の16進数、8進数およびバイナリ・リテラル(それぞれ10進値2147483647 (231-1)を表す)は、それぞれ次のとおりです。

  • 0x7fff_ffff,

  • 0177_7777_7777および

  • 0b0111_1111_1111_1111_1111_1111_1111_1111

intの最も負の16進リテラル、8進リテラルおよび2進リテラルで、それぞれ10進値-2147483648 (-231)を表します。

  • 0x8000_0000,

  • 0200_0000_0000および

  • 0b1000_0000_0000_0000_0000_0000_0000_0000

次の16進リテラル、8進リテラルおよび2進リテラルは、10進値-1を表します。

  • 0xffff_ffff,

  • 0377_7777_7777および

  • 0b1111_1111_1111_1111_1111_1111_1111_1111

16進、8進またはバイナリのintリテラルが32ビットに収まらない場合、コンパイル時にエラーが発生します。

long型の最大の10進リテラルは、9223372036854775808L (263)です。

0Lから9223372036854775807Lまでのすべての10進リテラルは、longリテラルが存在する任意の場所に存在できます。 小数リテラル9223372036854775808Lは、単項マイナス演算子-のオペランドとしてのみ指定できます(§15.15.4)。

10進リテラル9223372036854775808Lが単項マイナス演算子のオペランド以外の場所にある場合、またはlong型の10進リテラルが9223372036854775808L (263)より大きい場合、コンパイル時にエラーが発生します。

long型の最大正の16進数、8進数およびバイナリ・リテラル(それぞれ10進値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の最も負の16進リテラル、8進リテラルおよび2進リテラルで、それぞれが10進値-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

次の16進リテラル、8進リテラルおよび2進リテラルは、10進値-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

16進、8進またはバイナリのlongリテラルが64ビットに収まらない場合、コンパイル時にエラーが発生します。

intリテラルの例:

0    2    0372    0xDada_Cafe    1996    0x00_FF__00_FF

longリテラルの例:

0l    0777L    0x100000000L    2_147_483_648L    0xC0B0L

3.10.2.  浮動小数点リテラル

浮動小数点リテラルには、整数部分、10進点または16進点(ASCIIピリオド文字で表される)、小数部分、指数および型接尾辞があります。

浮動小数点リテラルは、10進数(10進数)または16進数(16進数)で表現できます。

小数浮動小数点リテラルでは、少なくとも1つの数字(整数部分または小数部分)と、小数点、指数または浮動小数点型の接尾辞が必要です。 その他のパーツはすべてオプションです。 指数が存在する場合は、ASCII文字eまたはEの後にオプションで符号付き整数が続きます。

16進数浮動小数点リテラルでは、少なくとも1つの桁(整数部または小数部のいずれか)が必要で、指数部は必須で、float型の接尾辞はオプションです。 指数部は、ASCII文字のpまたはPの後に、オプションで符号付きの整数値が続きます。

アンダースコアは、整数部分を示す桁と、小数部分を示す桁と指数を表す桁の間のセパレータとして使用できます。

ExponentIndicator:
(いずれか)
e E
SignedInteger:
Sign:
(いずれか)
+ -
FloatTypeSuffix:
(いずれか)
f F d D
HexadecimalFloatingPointLiteral:
HexSignificand:
BinaryExponentIndicator:

p P(のひとつ)

浮動小数点リテラルは、ASCII文字Fまたはfで接尾辞が付けられている場合はfloat型で、それ以外の場合はdouble型で、オプションでASCII文字Dまたはdで接尾辞を付けることができます。

float型とdouble型の要素は、それぞれIEEE 754 binary32およびIEEE 754 binary64浮動小数点形式を使用して表すことができる値です(§4.2.3)。

浮動小数点数のUnicode文字列表現から内部IEEE 754バイナリ浮動小数点表現への適切な入力変換の詳細は、クラスFloatvalueOfおよびパッケージjava.langのクラスDoubleのメソッドで説明されています。

float型の最大と最小の正の数値リテラルは次のとおりです:

  • 最大の正の有限値 floatは(2 - 2-23) 2127と数値的に等しくなります。

    この値に丸める最短の10進リテラルは、3.4028235e38fです。

    この値の16進リテラルは0x1.fffffeP+127fです。

  • 最小の正の有限ゼロ以外のfloat値は、数値的に2-149と等しくなります。

    この値に丸める最短の10進リテラルは、1.4e-45fです。

    この値に対する2つの16進リテラルは、0x0.000002P-126fおよび0x1.0P-149fです。

double型の最大および最小の正のリテラルは次のとおりです。

  • 最大の正の有限値 doubleは(2 - 2-52) 21023と数値的に等しくなります。

    この値に丸める最短の10進リテラルは、1.7976931348623157e308です。

    この値の16進リテラルは0x1.f_ffff_ffff_ffffP+1023です。

  • 最小の正の有限ゼロ以外のdouble値は、数値的に2-1074と等しくなります。

    この値に丸める最短の10進リテラルは、4.9e-324です。

    この値に対する2つの16進リテラルは、0x0.0_0000_0000_0001P-1022および0x1.0P-1074です。

ゼロ以外の浮動小数点リテラルが大きすぎる場合はコンパイル時にエラーが発生するため、その内部表現への丸め変換時にIEEE 754無限大になります。

プログラムは、1f/0f-1d/0dなどの定数式を使用するか、クラスFloatおよびDoubleの事前定義定数POSITIVE_INFINITYおよびNEGATIVE_INFINITYを使用して、コンパイル時エラーを生成せずに無限性を表すことができます。

ゼロ以外の浮動小数点リテラルが小さすぎる場合、コンパイル時にエラーが発生し、その内部表現への丸め変換時にゼロになります。

ゼロ以外の浮動小数点リテラルの値が小さく、その内部表現への丸め変換時にゼロ以外の非正規数になる場合、コンパイル時エラーは発生しません。

Not-a-Number値を表す事前定義定数は、クラスFloatおよびDoubleFloat.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. ブール・リテラル

boolean型には、ブール・リテラルtrueおよびfalseで表され、ASCII文字から形成される2つの値があります。

BooleanLiteral:
(いずれか)
true false

ブール・リテラルは、常にboolean型です(§4.2.5)。

3.10.4.  文字リテラル

文字リテラルは、ASCII一重引用符で囲まれた文字またはエスケープ・シーケンス(§3.10.7)で表されます。 (一重引用符(アポストロフィ)文字は\\u0027です。)

CharacterLiteral:
SingleCharacter:
'または\\ではなくInputCharacter

文字リテラルは常にchar型です(§4.2.1)。

文字リテラルのコンテンツは、先頭の'に続くSingleCharacterまたはEscapeSequenceです。

コンテンツに続く文字が'以外の文字である場合、コンパイル時にエラーが発生します。

行の終了文字(§3.4)が'のオープン後および'のクローズ前に表示されるのは、コンパイル時のエラーです。

文字CRおよびLFはInputCharacterではなく、それぞれがLineTerminatorを構成するものとして認識されるため、エスケープ・シーケンス\\ LineTerminatorでも文字リテラルでは使用できません。

文字リテラルで表される文字は、文字リテラルの内容が、String.translateEscapesを実行したかのように、エスケープシーケンスが解釈されたものです。

文字リテラルは、UTF-16コード単位(§3.1)のみを表すことができます。つまり、\\u0000から\\uffffまでの値に制限されます。 文字リテラルで補助文字を表現しようとすると、コンパイル時にエラーが発生します。 補足文字は、使用するAPIに応じて、charシーケンス内のサロゲート・ペアとして、または整数として表す必要があります。

次に、charリテラルの例を示します。

  • 'a'

  • '%'

  • '\t'

  • '\\'

  • '\''

  • '\u03a9'

  • '\uFFFF'

  • '\177'

  • '™'

Unicodeエスケープは非常に早期に処理されるため、値が行送り(LF)である文字リテラルに対して'\\u000a'を記述することは正しくありません。Unicodeエスケープ\\u000aは、変換ステップ1(§3.3)で実際の行送りに変換され、行送りはステップ2(§3.4)でLineTerminatorになるため、文字リテラルはステップ3では有効ではありません。 かわりに、エスケープ・シーケンス'\\n'を使用する必要があります。 同様に、値がキャリッジ・リターン(CR)である文字リテラルに対して'\\u000d'を記述することは正しくありません。 かわりに、'\\r'を使用してください。 最後に、アポストロフィ(')を含む文字リテラルに対して'\\u0027'を記述することはできません。

CおよびC++では、文字リテラルに複数の文字の表現が含まれることがありますが、このような文字リテラルの値は実装定義です。 Javaプログラミング言語では、文字リテラルは常に正確に1文字を表します。

3.10.5.  文字列リテラル

文字列リテラルは、二重引用符で囲まれた0個以上の文字で構成されます。 改行などの文字は、エスケープ・シーケンスで表すことができます(§3.10.7)。

StringLiteral:
StringCharacter:

文字列リテラルは、常に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エスケープは非常に早期に処理されるため、単一の改行(LF)を含む文字列リテラルに対して"\\u000a"を記述することは正しくありません。Unicodeエスケープ\\u000aは、変換ステップ1 (§3.3)で実際の改行に変換され、改行がステップ2 (§3.4)でLineTerminatorになるため、ステップ3では文字列リテラルは有効ではありません。 かわりに、エスケープ・シーケンス"\\n"を使用する必要があります。 同様に、単一キャリッジ・リターン(CR)を含む文字列リテラルに対して"\\u000d"を記述することは正しくありません。 かわりに、"\\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

次の例では、6つのポイントを説明します。

  • 同じクラスおよびパッケージ内の文字列リテラルは、同じStringオブジェクトへの参照を表します(§4.3.1)。

  • 同じパッケージ内の異なるクラスの文字列リテラルは、同じStringオブジェクトへの参照を表します。

  • 異なるパッケージ内の異なるクラス内の文字列リテラルも、同じStringオブジェクトへの参照を表します。

  • 定数式(§15.29)から連結された文字列は、コンパイル時に計算され、リテラルであるかのように扱われます。

  • 実行時に連結によって計算された文字列は新しく作成されるため、区別されます。

  • 計算された文字列を明示的にインターンした結果は、同じ内容の既存の文字列リテラルと同じStringオブジェクトになります。


3.10.6.  テキスト・ブロック

テキスト・ブロックは、0個以上の文字で構成されており、区切り文字の先頭と末尾で囲まれています。 文字はエスケープ・シーケンス(§3.10.7)で表すことができますが、文字列リテラル(§3.10.5)でエスケープ・シーケンスで表す必要がある改行および二重引用符文字は、テキスト・ブロックで直接表すことができます。

TextBlockWhiteSpace:

便宜上、§3.3§3.4、および §3.6の次のプロダクションがここに示されています。

WhiteSpace:
ASCII SP文字(スペースとも呼ばれる)
ASCII HT文字(水平タブとも呼ばれる)
ASCII FF文字(フォーム・フィードとも呼ばれる)
LineTerminator
LineTerminator:
ASCII LF文字(「復帰」とも呼ばれる)
ASCII CR文字(「復帰」とも呼ばれる)
ASCII CR文字のあとにASCII LF文字が続く
InputCharacter:
UnicodeInputCharacter ただしCRまたはLFは除く
UnicodeInputCharacter:
RawInputCharacter:
UTF-16で表現可能な任意のUnicode文字

テキスト・ブロックは、常にString型です(§4.3.3)。

オープン・デリミタは、3つの二重引用符文字(""")で始まるシーケンスで、スペース、タブおよびフォーム・フィード文字が0個以上続いて終了し、行終了記号で終了します。

終了デリミタは、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つの二重引用符文字が表示される場合です。この場合、終了デリミタを模倣しないようにするには、少なくとも1つの二重引用符をエスケープする必要があります。

例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つの連続する二重引用符文字が(§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
            \""";
            """;
    }
}

テキスト・ブロックで表される文字列は、コンテンツ内の文字のリテラル・シーケンスではありません かわりに、テキスト・ブロックによって表される文字列は、コンテンツに次の変換を順番に適用した結果です:

  1. 行の終了文字は、次のようにASCII LF文字に正規化されます。

    • ASCII CR文字とそれに続くASCII LF文字は、ASCII LF文字に変換されます。

    • ASCII CR文字は、ASCII LF文字に変換されます。

  2. 偶発的な空白は、ステップ1の結果の文字に対してString.stripIndentを実行した場合のように削除されます。

  3. エスケープ・シーケンスは、ステップ2の結果の文字に対してString.translateEscapesを実行した場合と同様に解釈されます。

この仕様で、テキスト・ブロックが特定の文字または文字シーケンスを含むこと、または特定の文字または文字シーケンスがテキスト・ブロックのにあることが示されている場合、テキスト・ブロックによって表される文字列(コンテンツ内の文字のリテラル・シーケンスとは対照的に)に文字または文字シーケンスが含まれていることを意味します。

例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と評価されます。

テキスト・ブロックは、文字列連結(§15.18.1)、Stringのインスタンスでのメソッドの起動、および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.7.  エスケープ・シーケンス

文字リテラル、文字列リテラルおよびテキスト・ブロック(§3.10.4§3.10.5§3.10.6)では、エスケープ・シーケンスによって、Unicodeエスケープ(§3.3)を使用せずに一部の非グラフィック文字を表現でき、一重引用符、二重引用符およびバックスラッシュ文字を使用できます。

EscapeSequence:
\ b (backspace BS, Unicode \u0008)
\ s (space SP, Unicode \u0020)
\ t (horizontal tab HT, Unicode \u0009)
\ n (linefeed LF, Unicode \u000a)
\ f (form feed FF, Unicode \u000c)
\ r (carriage return CR, Unicode \u000d)
\ LineTerminator (line continuation, no Unicode representation)
\ " (double quote ", Unicode \u0022)
\ ' (single quote ', Unicode \u0027)
\ \ (backslash \, Unicode \u005c)
OctalEscape (octal value, Unicode \u0000 to \u00ff)
OctalDigit:
(いずれか)
0 1 2 3 4 5 6 7
ZeroToThree:
(いずれか)
0 1 2 3

前述のOctalDigit本番は、§3.10.1に基づいています。 8進数エスケープはCとの互換性のために提供されていますが、\\u0000から\\u00FFまでのUnicode値のみを表現できるため、通常、Unicodeエスケープが推奨されます。

エスケープ・シーケンス内のバックスラッシュに続く文字がLineTerminatorまたはASCIIのbstnfr"'\\0123456または7でない場合、コンパイル時にエラーが発生します。

文字リテラル、文字列リテラル、またはテキストブロックのコンテンツ内のエスケープシーケンスは、解釈され、その\と末尾の文字が、EscapeSequence文法におけるUnicodeエスケープで表される単一の文字に置き換えられます。 行の継続エスケープ・シーケンスには、対応するUnicodeエスケープがないため、これは何にも置き換えられずに解釈されます。

行継続エスケープ・シーケンスはテキスト・ブロックに指定できますが、文字リテラルまたは文字列リテラルでは指定できません。これは、それぞれがLineTerminatorを許可しないためです。

3.10.8.  nullリテラル

NULL型には、NULLリテラルnullで表される1つの値(NULL参照)があり、これはASCII文字から形成されます。

NullLiteral:
null

nullリテラルは常にnull型(§4.1)です。

3.11.  セパレータ

ASCII文字から形成される12個のトークンは、区切り文字(句読点)です。

Separator:
(次のうちの1つ)
(   )   {   }   [   ]   ;   ,   .   ...   @   ::

3.12. 演算子

ASCII文字から形成される38個のトークンが演算子です。

Operator
(次のうちの1つ)
=   >   <   !   ~   ?   :   ->
==  >=  <=  !=  &&  ||  ++  --
+   -   *   /   &   |   ^   %   <<   >>   >>>
+=  -=  *=  /=  &=  |=  ^=  %=  <<=  >>=  >>>=