💬

Kotlinで${}しないといけないところ

2022/12/04に公開

前提:Kotlinで変数を埋め込む

kotlinで文字列内に変数を埋め込みたいときには以下のようにかけます。

文字列に変数を埋め込む
val name = "TBSten"
println("こんにちは!$name!")  // "こんにちは!TBSten!"

ですが時々これではいけない場合があります。

エラーになる時
val name = "TBSten"
println("こんにちは!$nameさんですね?")  // エラー

そんな時は{}で囲むとうまくいきます。

エラーになるときは{}で囲む
val name = "TBSten"
println("こんにちは!${name}さんですね?")  // エラー

本記事ではどんなときに{}で囲わないといけないかを解説します。

結論:変数名として使える文字が後に続くと変数が見つからないエラーになる

公式ドキュメントを見てみる

https://kotlinlang.org/docs/strings.html#string-templates

ドキュメント中に以下の記述があります。

$未加工の文字列 (バックスラッシュのエスケープをサポートしていない) で、識別子の先頭として許可されている記号の前にドル記号を挿入するには、次の構文を使用します。

例えば

println("ab$namecd")

とあった場合、Kotlinのコンパイラは以下のように解釈を進めます。

  1. "があるからここから"までは文字列なんだ!よし一文字ずつ読み進めてみよう
  2. 次の文字はaだ。これは文字列の1文字目だな
  3. 次の文字はbだ。これは文字列の2文字目だな
  4. 次の文字は$だ。おっここからは埋め込みたい変数の名前がくるのね。じゃあ変数の名前はなんだろう...
  5. 次の文字はnだ。変数名の1文字目はnだな
  6. 次の文字はaだ。変数名の2文字目はnだな
  7. 次の文字はmだ。変数名の3文字目はnだな
  8. 次の文字はeだ。変数名の4文字目はnだな
  9. 次の文字はcだ。変数名の5文字目はcだな<-- 🈁 ポイント!
  10. 次の文字はdだ。変数名の6文字目はdだな
  11. 次の文字は"だ。ここまでが文字列なのね。じゃあ最初に文字列"ab"その次に変数namecdを埋め込みたいのね。あれ?namecdなんて変数ないぞ?(エラー)

上記の通りKotlinコンパイラは$の後に変数名として使える文字が続く限りそれらを埋め込みたい変数名として解釈してしまいますcdのような文字は変数名として使用できるので上記の9以降のように変数名として読み進められてしまうわけです。

ちなみにアルファベット以外の文字(日本語など)も変数名として使用できます。(注:一部ケースを除いてなるべくすべきではないです)

val 名前 = "TBSten"
val 年齢 = 100_000_000

なので"こんにちは!$nameさんですね?"としても$以降の文字で変数名として使える文字はnameさんですねとなりnameさんですねなんて変数はないのでコンパイルエラーが発生します。

よって「埋め込みたい変数名はここまでだよ」と教えるために{}で囲んであげる必要があるのです。

Discussion