Kotlin 基本数据类型(三):Booleans、Characters
基本操作
在 Kotlin 中,使用 String 类型来表示字符串。
通常来说,字符串是使用双引号(")包裹起来的字符序列:
kotlin
val str = "abcd 123"
我们开发者可以使用索引符号 [],来访问字符串中的字符。因此,也可以使用迭代来循环字符:
kotlin
for (c in str) {
println(c)
}
字符串是不可变的。只要我们开发者初始化了一个字符串,那么就无法改变它的值了,并且也无法赋予新的值。所有的字符串操作都会返回一个新的字符串,原始的字符串是不变的:
kotlin
val str = "abcd"
// Creates and prints a new String object
println(str.uppercase())
// ABCD
// The original string remains the same
println(str)
// abcd
开发者可以使用 + 号操作符来连接字符串。同样地,开发者也可以使用 + 号连接符来连接其他的类型,只要被连接的第一个元素是字符串即可:
kotlin
val s = "abc" + 1
println(s + "def")
// abc1def
字符串常量
Kotlin 有两种类型的字符串常量:
- Escaped strings(转义字符串)
- Multiline strings(多行字符串)
Escaped strings
转义字符串可以包含转义字符。 下面是转义字符串的一个示例:
kotlin
val s = "Hello, world!\n"
开发者使用 反斜杠 () 来实现转义。
Multiline strings
多行字符串可以包含换行符和任意文本,它由三重引号(""")分隔。需要注意的是,它不包含转义字符(转义字符被视为普通文本):
kotlin
val text = """
for (c in "foo")
print(c)
"""
可以使用 trimMargin () 函数来移除多行字符串中前导空白:
kotlin
fun main() {
val text = """
|Tell me and I forget.
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""";
println(text)
println(text.trimMargin())
}

字符串模板
字符串常量可以包含模板表达式。模板表达式是指代码片段,代码片段求值的结果会被拼接到字符串。处理模板表达式时,Kotlin 会自动调用结果的 toString 方法,并将 toString 的结果连接进原字符串。
模板表达式以美元符号($)开始,可以是一个变量:
kotlin
val i = 10
println("i = $i")
// i = 10
val letters = listOf("a","b","c","d","e")
println("Letters: $letters")
// Letters: [a, b, c, d, e]
也可以是花括号括起来的表达式:
kotlin
val s = "abc"
println("$s.length is ${s.length}")
// abc.length is 3
开发者可以在多行字符串和转义字符串中使用字符串模板。但是,多行字符串不支持转义字符串。所以,想要在多行字符串中使用美元符号$,需要遵循以下语法:
kotlin
val price = """
${'$'}_9.99
"""
多美元符号字符串插值
多美元符号字符串插值是指开发者可以指定需要多少个连续美元符号触发插值。插值是指将变量或表达式直接嵌入字符串的过程。
虽然你可以对单行字符串中的字面量进行转义,但 Kotlin 中的多行字符串不支持反斜杠转义。要将美元符号 作为字面字符包含在内,必须使用 {'$'} 结构来阻止字符串插值。这种方法可能会使代码更难阅读,尤其是当字符串包含多个美元符号时。
所以多美元符号简化了操作,允许开发者在单行和多行字符串中都将美元符号视为字面字符:
kotlin
val KClass<*>.jsonSchema : String
get() = $$"""
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"$dynamicAnchor": "meta",
"title": "$${simpleName ?: qualifiedName ?: "unknown"}",
"type": "object"
}
"""
上面的例子中, $$ 指定了需要两个美元符号才触发插值,单一的美元符号都会被视为是个字符常量。
开发者同样可以调整美元符号的数量。比如使用三个美元符号,这样的话一个美元符号、两个美元符号都会被视为字符常量:
kotlin
val productName = "carrot"
val requestedData =
$$$"""{
"currency": "$",
"enteredAmount": "42.45 $$",
"$$serviceField": "none",
"product": "$$$productName"
}
"""
println(requestedData)
//{
// "currency": "$",
// "enteredAmount": "42.45 $$",
// "$$serviceField": "none",
// "product": "carrot"
//}
上面的例子,$$ 前缀允许字符串包含 和 $$,而无需使用{'$'} 结构进行转义。
字符串格式化
开发者可以使用String.format()
函数来实现特定的格式化需求。
String.format()
函数接受一个格式字符串和一个或者多个的参数。格式字符串包含一个 % 表示的占位字符串,后跟着一个特定的格式化说明符。 格式化说明符是一个包含:标志,宽度,精度,转换类型的格式化指令。格式化说明符决定了输出的格式。%d用于整数,%f用于浮点数,%s用于字符串。开发者也可以使用 argument_index$
语法以不同的格式来多次引用同一个参数。
kotlin
// Formats an integer, adding leading zeroes to reach a length of seven characters
val integerNumber = String.format("%07d", 31416)
println(integerNumber)
// 0031416
// Formats a floating-point number to display with a + sign and four decimal places
val floatNumber = String.format("%+.4f", 3.141592)
println(floatNumber)
// +3.1416
// Formats two strings to uppercase, each taking one placeholder
val helloString = String.format("%S %S", "hello", "world")
println(helloString)
// HELLO WORLD
// Formats a negative number to be enclosed in parentheses, then repeats the same number in a different format (without parentheses) using `argument_index$`.
val negativeNumberInParentheses = String.format("%(d means %1\$d", -31416)
println(negativeNumberInParentheses)
String.format()
的功能和模板字符串类似,但是,String.format()
函数更加灵活。
另外,开发者可以声明一个格式化字符串。在需要变化的场景中,这种方式非常有用,比如在依赖用户本地化的设置。
String.format()
是把双刃剑,灵活的同时,也很容易出现参数的数量或位置与其对应的占位符不匹配的情况。