1. 概述
本教程将介绍如何在 Scala 中使用字符串插值(String Interpolation)功能。
✅ 字符串插值是一种在字符串字面量中使用占位符,并在运行时将其替换为实际值的技术。
它使得字符串拼接更加直观、可读性更强,是现代编程语言中非常常见的特性。
2. s
插值器
✅ s
插值器是最常用的字符串插值方式,它允许我们直接在字符串中嵌入变量:
val age = 30
val agePresentation = s"I am $age"
// 结果: "I am 30"
⚠️ 如果你不想让 $
被解析为变量占位符,可以用双写 $
来转义:
"It is about $$30"
// 结果: "It is about $30"
3. f
插值器
✅ f
插值器是类型安全的,并且语法与 Java 中的 printf
非常相似,适合格式化输出:
val height = 1.7d
val name = "Michele"
println(f"My name is $name%s. I am $age%d years old and $height%1.2f meters tall")
// 输出: My name is Michele. I am 30 years old and 1,70 meters tall
println(f"My name is $name%d.")
// 编译报错: type mismatch!
// found : String - required: Int
📌 所有格式化规则都与 Java 的 Formatter
类一致,可以参考 Java 格式化文档
4. raw
插值器
✅ raw
插值器不会对字符串中的特殊字符进行转义处理,这一点与 s
和 f
不同。
来看个例子更直观:
raw"My name is $name%s. \n $agePresentation and $height%1.2f meters"
// 输出: My name is Michele%s. \n I am 30 and 1.7%1.2f meters
f"My name is $name%s. \n $agePresentation and $height%1.2f meters tall"
/*
输出:
My name is Michele.
I am 30 and 1.70 meters tall
*/
📌 看出区别了吗?\n
在 raw
中不会被解释为换行符。
5. 在插值中转义双引号
有时候我们需要在插值字符串中插入双引号 "
, 这时候可以借助 $
元字符来处理。
首先定义一个双引号常量:
val DOUBLE_QUOTE: Char = '"'
然后在 s
插值中使用 ${}
包裹变量:
val actual: String = s"Hello, ${DOUBLE_QUOTE}world!${DOUBLE_QUOTE}"
val expected = "Hello, " + DOUBLE_QUOTE + "world!" + DOUBLE_QUOTE
assert(expected == actual)
✅ 正常工作!
📌 在 Scala 3 中,你甚至可以直接写 "
, 而无需变量表达式:
val actual: String = s"Hello, $"world!$""
在 f
插值中也一样:
"Escape using metachar in f-interpolation" should "include double quote character" in {
val actual: String = f"Hello, ${DOUBLE_QUOTE}world!${DOUBLE_QUOTE}"
val expected = "Hello, " + DOUBLE_QUOTE + "world!" + DOUBLE_QUOTE
assert(expected == actual)
}
6. 自定义插值器
✅ Scala 支持自定义字符串插值器,你可以根据自己的需求实现插值逻辑。
下面是一个简单的例子:实现一个插值后自动转大写的插值器:
implicit class CustomInterpolator(val sc: StringContext) extends AnyVal {
def custom(args: Any*): String = {
val stringContextIterator = sc.parts.iterator
val argsIterator = args.iterator
val sb = new java.lang.StringBuilder(stringContextIterator.next())
while (argsIterator.hasNext) {
sb.append(argsIterator.next().toString)
sb.append(stringContextIterator.next())
}
sb.toString.toUpperCase()
}
}
📌 这个方法定义在 StringContext
的隐式类中,接收任意参数,并拼接后转为大写。
使用方式如下:
val testString = "well"
custom"the custom interpolator works $testString as expected"
// 输出: THE CUSTOM INTERPOLATOR WORKS WELL AS EXPECTED
编译器会自动将上面的代码展开为:
new StringContext("the custom interpolator works ", " as expected").custom(testString)
📌 这样,自定义逻辑就可以正确执行了。
7. 总结
在这篇文章中,我们详细介绍了 Scala 中三种内置的字符串插值器:
s
: 最基础、最常用的插值方式f
: 类型安全、支持格式化输出raw
: 不转义特殊字符,适合原始字符串处理
此外,我们还展示了如何创建自定义插值器,以便满足特定业务场景的需求。
✅ 本文完整代码示例可以在这里找到:GitHub 仓库链接