Java : エスケープシーケンスの基本
エスケープシーケンスを使うと、文字列リテラルとして、改行やタブなどの非グラフィックス文字を表記できます。
代表的なエスケープシーケンスには、
- \n … 改行(LF)
- \r … 行頭復帰(CR)
- \t … タブ
などがあります。
本記事では、そんなエスケープシーケンスの基本をご紹介します。
注意:
- エスケープシーケンスには、バックラッシュ ( \ ) が使われます。
ただし、環境によっては円記号 ( ¥ ) で表示されることもあります。 - 本記事でも \ と ¥ が混在して表示されるかもしれません。
その場合は、どちらも同じものとしてご理解ください。
概要
エスケープシーケンスを使うと、
- 文字リテラル
- 文字列リテラル
- テキストブロック
で、改行やタブなどの非グラフィック文字を表記できるようになります。
リテラルとは、ソースコード上で文字や文字列の値を直接表記したものをいいます。
// 文字列リテラルの例
final String str = "abcde";
例えば文字列のリテラルは、
"abcde"
というように、文字列をダブルクォート文字 ( " ) で囲むことで表記します。
次に、文字列リテラルで改行を表記する例を見てみましょう。
final String str = "abc\n123\nあいうえお";
System.out.println(str);
結果は次のように表示されます。
abc
123
あいうえお
改行のエスケープシーケンスは \n です。
文字列リテラルとしては
"abc\n123\nあいうえお"
という1行で表記されます。
しかし、それを実際に表示すると \n は改行になります。
このように、改行のような非グラフィック文字をリテラルとして表記するための仕組みが エスケープシーケンス です。
補足
- リテラル表記の詳細については「リテラルの表記方法いろいろ」の記事もご参照ください。
なぜエスケープシーケンスが必要なのか
もしエスケープシーケンスを知らないかたが、文字列リテラルに改行を入れたいと考えたとき、
final String str =
"abc
123
あいうえ";
と表記したくなるかもしれません。
しかし、これはコンパイルエラーとなります。
Javaの構文的に許容されていないためですね。
他には、ダブルクォート文字 ( " ) そのものを文字列リテラルで表記したい場合も、エスケープシーケンスがないと困ることになります。
final String str = "aaa"bbb";
aaa と bbb の間にダブルクォート文字 ( " ) を入れたいのですが、これもコンパイルエラーとなります。
ダブルクォート文字が3つあるので、どれが文字列リテラルの開始と終了の " なのか、Javaコンパイラが判断できないためです。
そこでエスケープシーケンスが必要になります。
ダブルクォート文字自体のエスケープシーケンスは、\" です。
final String str = "aaa\"bbb";
System.out.println(str);
// 結果
// ↓
//aaa"bbb
エスケープシーケンスを使い、文字列リテラリでダブルクォート文字が表記できました。
aaa と bbb の間のダブルクォート文字( " )は、バックスラッシュ( \ ) があるのでエスケープシーケンスです。
Javaコンパイラは \" をいったん除外して、aaaの前の " と bbb の後の " をリテラル文字列の開始と終了であると判断できます。
まとめると…
文字や文字列リテラルの表記では、表現できる文字に構文上の限界があります。
その限界を回避するための手段が エスケープシーケンス というわけですね。
基本的なエスケープシーケンス一覧
基本的なエスケープシーケンスの一覧になります。
エスケープシーケンス | 簡単な説明 | ユニコード表記 |
---|---|---|
\b | バックスペース | \u0008 |
\s | スペース | \u0020 |
\t | タブ | \u0009 |
\n | 改行(LF) | \u000a |
\f | 改ページ(FF) | \u000c |
\r | 行頭復帰(CR) | \u000d |
\" | ダブルクォート文字 | \u0022 |
\' | シングルクォート文字 | \u0027 |
\\ | バックスラッシュ文字 | \u005c |
エスケープシーケンスの基本構文は
- \ + 特定の文字
となります。
ユニコードエスケープ
ユニコードエスケープは、ユニコード値で直接文字を指定するエスケープシーケンスです。
- \u + 16進数表記の4桁の数字(ユニコード値)
で表記します。
ユニコード値は、例えば 'a' という文字には 0x0061、'あ' という文字には 0x3042 が割り当てられています。
以下、ユニコードエスケープを使ったコード例となります。
final String str = "\u0061\u0062\u0063";
System.out.println(str);
// 結果
// ↓
//abc
final String str = "\u3042\u3044\u3046";
System.out.println(str);
// 結果
// ↓
//あいう
補足
- ユニコードとは、世界中の文字の1つ1つに通し番号(コード)を割り当てたものです。
詳細は「Unicode - Wikipedia」などをご参照ください。 - エスケープシーケンスの1つに、OctalEscapeがあります。
ただし、Java SE 言語仕様にて、代わりにユニコードエスケープを使うことが推奨されているため、本記事では割愛しています。
改行の抑止
改行の抑止は、テキストブロックでのみ使えるエスケープシーケンスです。
まずは、改行をエスケープしない例を見てみましょう。
final String textBlock = """
aaa
123
あいうえお
""";
System.out.println(textBlock);
// 結果
// ↓
//aaa
//123
//あいうえお
テキストブロックでは、ソースコード上で改行すれば、それは文字列の改行 ( \n ) となります。
次に改行をエスケープする例になります。
final String textBlock = """
aaa\
123\
あいうえお\
""";
System.out.println(textBlock);
// 結果
// ↓
//aaa123あいうえお
テキストブロックの各行の最後をバックスラッシュ( \ ) にすることで、テキストブロックによる改行を抑止できます。
例えば、非常に長い1行のテキストを、
- ソースコード上では改行して見やすく
- でも、実際の文字列には改行は含めない
という場面で使えそうですね。
テキストブロックのすすめ
リテラル表記中にエスケープシーケンスが多いと、けっこうコードが見づらくなります。
final var str = "<root>\n" +
" <child attr=\"abc\"/>\n" +
"</root>\n";
System.out.println(str);
// 結果
// ↓
//<root>
// <child attr="abc"/>
//</root>
上記は、シンプルなXML文字列の例ですが、意外と見づらくはないでしょうか。
そんなときは、テキストブロックを使うことをおすすめします。
Java 15 から追加された仕様で、改行やダブルクォート文字をエスケープなしで表記できます。
final var textBlock = """
<root>
<child attr="abc"/>
</root>
""";
System.out.println(textBlock);
// 結果
// ↓
//<root>
// <child attr="abc"/>
//</root>
テキストブロックを使った例になります。
だいぶ見やすくなったのではないでしょうか。
テキストブロックについてもう少し詳しく知りたいかたは、「テキストブロックの基本」も参照いただければ幸いです。