Overview
本节主要介绍四种语言中的字符串的相关用法。由于字符串的 API 众多,所以本节只挑几个主要的来讲。
Java 篇
声明字面量
String s = "Hello World";
遍历字符串
for (char c : s.toCharArray()) {
System.out.println(c);
}
多行文本
String text =
"\t1, 2, 3\n" +
"\tone, two, three\n" +
"\t\"x\", \"y\", \"z\"";
在 Java 中表示多行文本和特殊字符时需要使用对应的转义符,看起来很不直观,尤其是碰到表示 XML 或者 JSON 的字符串更是让人头痛。
字符串模板 Template
所谓的字符串模板或者说字符串插值就是使用变量或表达式的结果来代替字符串中的特殊占位符。
Java 语言本身并没有字符串模板,要想实现模板功能只有自己解析字符串,使用 replace()
等方法来进行模拟。
例:
String name = "Peter";
String str = "name=$name, ${name.length()}";
System.out.println(
str.replace("$name", name)
.replace("${name.length()}", "" + name.length()));
或者也可以使用 format()
方法来实现
例
System.out.println(String.format("name=%s, %d", name, name.length()));
总的来说使用起来并不方便。
常用方法
// 获取某一位置的字符
System.out.println(s.charAt(2)); // l
// 截取子串
System.out.println(s.substring(6, 9)); // Wor
StringBuilder
由于 Java 中字符串是不可变的,所以直接连接字符串会创建大量对象。因此 Java 提供了非同步版本的 StringBuilder
和同步的 StringBuffer
来用于创建字符串池。
例
StringBuilder content = new StringBuilder();
content.append("hello");
content.append(",");
content.append("\nworld");
content.append("!").append("!");
System.out.println(content);
需要注意不要使用 append("foo" + "bar")
这样的形式而是使用 append("foo").append("bar")
,因为前者完全丧失了 StringBuffer
的功能。
Groovy 篇
声明字面量
def s = "Hello World"
遍历字符
for (c in s) {
println(c)
}
多行文本
def text =
""" 1, 2, 3
one, two, three
"x, "y", "z\""""
Groovy 中可以使用三个双引号表示按原样输出,即在三个双引号之间可以任意换行,使用特殊字符等,这种设计使 Groovy 中表示 XML 和 JSON 文本时更加简单清晰。
需要注意如果要输出的字符串结尾也是双引号,则必须像以上例子一样在最后一个双引号前加上转义符 "",否则编译器会将此双引号和三个双引号看做是两组双引号而报编译错误。
字符串模板 Template
def name = "Peter"
def str = "name=${name}, ${if (name.length() > 10) 10 else name.length()}"
println(str) // name=Peter, 5
Groovy 中可以使用 ${}
来实现字符串模板,大括号之间的字符会被解析为代码并执行,执行的结果会被当做字符串来输出,看起来就像是使用 Javascript 的 eval
函数一样,比起 Java 来说方便许多,再也不用使用一堆加号连接字符串和变量了。
GString
Groovy 和 Javascript 在字符串使用时有一个共同点,就是可用使用单引号或双引号来表示字符串,大部分情况下这两者都是一样的用法。但是使用模板时必须使用双引号,因为包含引用符号 ${}
的以双引号包裹的字符串会被解析为 Groovy 内置的字符串类 GString。该类是 String 类的补充,拥有很多 Groovy 语言的方法。而单引号字符串或不包含引用符号的字符串都会被解析为普通的 Java String 类,也就没有模板等功能了。
常用方法
// 获取某一位置的字符
println(s[2]) // l
// 截取字符串,"<" 表示不包含
println(s[6..9]) // Worl
println(s[6..<9]) // Wor
// 返回从字符串中减去某一部分的新字符串
println(s - "l" - "World") // Helo
StringBuilder
Groovy 可以直接使用更简便的符号 <<
追加子串。
def content = new StringBuilder()
content.append "hello"
content << ","
content << "\nworld"
content << "!" << "!"
Scala 篇
声明字面量
val s = "Hello World"
遍历字符
for (c <- s) {
println(c)
}
多行文本
Scala 的多行文本使用方式与 Groovy 基本一致
val text =
""" 1, 2, 3
one, two, three
"x, "y", "z""""
字符串模板 Template
Scala 的字符串模板主要依赖于两种插值器(Interpolator):s 插值器和 f 插值器
s 插值器
s 插值器主要用于进行简单的字符串替换,声明时直接使用字符 "s" 连接字符串且当中不要有空格。
例
val name = "Peter"
val str = s"name=$name, ${if (name.length() > 10) 10 else name.length}"
println(str) // name=Peter, 5
f 插值器
f 插值器主要用于进行格式化输出,类似 String.format()
的功能。
例
val salary = 100.1
println(f"$name%s has $salary%.5f") // Peter has 100.10000
常用方法
// 获取某一位置的字符
println(s.charAt(2)) // l
// 截取字符串
println(s.substring(6,9)) // Wor
StringBuilder
Scala 中除了 append()
方法也可以用重载的操作符进行修改。
val content = new StringBuilder
content append "hello"
content += ','
content ++= "\nworld"
content ++= "!" ++= "!"
+=
用于添加字符,由于 Scala 中将字符串视为字符的集合所以可以用 ++=
添加字符串。
Kotlin 篇
声明字面量
val s = "Hello World"
遍历字符
for (c in s) {
println(c)
}
多行文本
同样使用三个引号
val text =
""" 1, 2, 3
one, two, three
"x, "y", "z""""
在使用多行文本时可以在字符串中添加边距符号,默认边距符号为 |
val textWithMargin =
"""
|Tell me and I forget.
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()
然后可以使用 trimMargin()
方法去除边距符号和其之前的所有空白字符,通过该种方式可用实现更细致的排版
字符串模板 Template
同样使用 ${}
符号
val name = "Peter"
val str = "name=${name}, ${if (name.length > 10) 10 else name.length}"
println(str) // name=Peter, 5
如果希望在字符串模板中使用 $
符号需要使用 ${'$'}
这样的形式才可以正常显示
"name=${'$'}{name}"
StringBuilder
Kotlin 中可以直接使用内置的 DSL 语句创建可变字符串
val content = buildString {
append("hello")
appendln(',') // 添加换行
append("world")
append("!", "!") // 添加多参数
}
常用方法
// 获取某一位置的字符
println(s[2])
// 截取字符串
println(s.substring(5, 8))
Summary
- 除了 Java 之外,其它三种语言都可用使用三个引号实现多行文本
- 除了 Java 之外,其它三种语言都支持字符串模板,其中 Scala 的语法略微不一样
- Groovy 支持 String 和对其进行扩展的 GString 两种字符串
文章源码见 https://github.com/SidneyXu/JGSK 仓库的 _07_string
小节