Scala中基础的字符串插值就是在字符串前面加字符s
,然后在字符串中放入变量,每个变量都应该用$
字符开头,eg.
val name = "Yrz"
val age = 4
val weight = 15.00
println(s"$name is $age years old, and his weight is $weight")
输出如下:
Yrz is 4 years old, and his weight is 15.0
在字符串的变量中使用表达式
除了把变量放到字符串中外,还可以使用花括号把表达式包起来再放到字符串中。根据官方文档,${}
内可以嵌入任何表达式,eg.
println(s"$name is ${age + 1} years old, and his weight is $weight")
输出如下:
Yrz is 5 years old, and his weight is 15.0
也可以在${}
中使用==
表达式,eg.
println(s"Is $name 4 years old? ${age == 4}")
输出如下:
Is Yrz 4 years old? true
可以通过${}
来输出对象中的变量,eg.
case class Student(val name:String, val score: Int)
val yrz:Student = new Student("Yrz", 100)
println(s"The score of ${yrz.name} is ${yrz.score}")
输出如下:
The score of Yrz is 100
s
是一个方法
作为插值的s
实际上是一个方法,在StringContext.scala
中定义如下:
/** The simple string interpolator.
*
* It inserts its arguments between corresponding parts of the string context.
* It also treats standard escape sequences as defined in the Scala specification.
* Here's an example of usage:
* {{{
* val name = "James"
* println(s"Hello, $name") // Hello, James
* }}}
* In this example, the expression $name is replaced with the `toString` of the
* variable `name`.
* The `s` interpolator can take the `toString` of any arbitrary expression within
* a `${}` block, for example:
* {{{
* println(s"1 + 1 = ${1 + 1}")
* }}}
* will print the string `1 + 1 = 2`.
*
* @param `args` The arguments to be inserted into the resulting string.
* @throws IllegalArgumentException
* if the number of `parts` in the enclosing `StringContext` does not exceed
* the number of arguments `arg` by exactly 1.
* @throws StringContext.InvalidEscapeException
* if a `parts` string contains a backslash (`\`) character
* that does not start a valid escape sequence.
*/
def s(args: Any*): String = standardInterpolator(treatEscapes, args)
字符串插值的好处:
- Scala提供了其他更强有力的插值函数;
- 可以自定义字符串插值函数;
字符串插值f
(printf
格式化)
上面的例子中,weight打印的是15.0,如果想打印更多小数位数,或者需要对数字进行格式化操作;这个可以使用“f字符串插值”,一个可以通过printf
格式化内部字符串的方法。$weight%.0f
保留0
位小数, eg.
println(f"$name is ${age + 1} years old, and his weight is $weight%.0f kg")
输出如下:
Yrz is 5 years old, and his weight is 15 kg
$weight%.2f
保留两位小数,eg.
println(f"$name is ${age + 1} years old, and his weight is $weight%.2f kg")
输出如下:
Yrz is 5 years old, and his weight is 15.00 kg
如上所述,只需要两步:
- 在字符串前加字母
f
; - 在变量之后使用
printf
的格式化操作符;
f
在StringContext.scala
中的源码如下:
/** The formatted string interpolator.
*
* It inserts its arguments between corresponding parts of the string context.
* It also treats standard escape sequences as defined in the Scala specification.
* Finally, if an interpolated expression is followed by a `parts` string
* that starts with a formatting specifier, the expression is formatted according to that
* specifier. All specifiers allowed in Java format strings are handled, and in the same
* way they are treated in Java.
*
* For example:
* {{{
* val height = 1.9d
* val name = "James"
* println(f"$name%s is $height%2.2f meters tall") // James is 1.90 meters tall
* }}}
*
* @param `args` The arguments to be inserted into the resulting string.
* @throws IllegalArgumentException
* if the number of `parts` in the enclosing `StringContext` does not exceed
* the number of arguments `arg` by exactly 1.
* @throws StringContext.InvalidEscapeException
* if a `parts` string contains a backslash (`\`) character
* that does not start a valid escape sequence.
*
* Note: The `f` method works by assembling a format string from all the `parts` strings and using
* `java.lang.String.format` to format all arguments with that format string. The format string is
* obtained by concatenating all `parts` strings, and performing two transformations:
*
* 1. Let a _formatting position_ be a start of any `parts` string except the first one.
* If a formatting position does not refer to a `%` character (which is assumed to
* start a format specifier), then the string format specifier `%s` is inserted.
*
* 2. Any `%` characters not in formatting positions must begin one of the conversions
* `%%` (the literal percent) or `%n` (the platform-specific line separator).
*/
// The implementation is hardwired to `scala.tools.reflect.MacroImplementations.macro_StringInterpolation_f`
// Using the mechanism implemented in `scala.tools.reflect.FastTrack`
def f[A >: Any](args: A*): String = macro ???
raw插入符
除s
和f
这两个字符串插入之外,Scala 2.10
也包含了其他的插入符,并命名为raw
插入符;raw
插入符“不会对字符串中的字符进行转义”。对比s
插入符和raw
插入符,eg:
println(s"foo\nbar")
输出如下:
foo
bar
println(raw"foo\nbar")
输出如下:
foo\nbar
想要避免\n这种操作符变成一个换行符的时候,raw
插入符将很有意义;
raw
在``中源码如下:
/** The raw string interpolator.
*
* It inserts its arguments between corresponding parts of the string context.
* As opposed to the simple string interpolator `s`, this one does not treat
* standard escape sequences as defined in the Scala specification.
*
* For example, the raw processed string `raw"a\nb"` is equal to the scala string `"a\\nb"`.
*
* ''Note:'' Even when using the raw interpolator, Scala will preprocess unicode escapes.
* For example:
* {{{
* scala> raw"\u005cu0023"
* res0: String = #
* }}}
*
* @param `args` The arguments to be inserted into the resulting string.
* @throws IllegalArgumentException
* if the number of `parts` in the enclosing `StringContext` does not exceed
* the number of arguments `arg` by exactly 1.
*/
def raw(args: Any*): String = standardInterpolator(identity, args)
def standardInterpolator(process: String => String, args: Seq[Any]): String = {
checkLengths(args)
val pi = parts.iterator
val ai = args.iterator
val bldr = new JLSBuilder(process(pi.next()))
while (ai.hasNext) {
bldr append ai.next
bldr append process(pi.next())
}
bldr.toString
}
官方文档:http://docs.scala-lang.org/overviews/core/string-interpolation.html#introduction