数字类型
Kotlin 提供了一组表示数字的内置类型。
整数
对于整数,有四种不同大小的类型,因此值的范围也不同。
所有以未超出 Int
最大值的整型值初始化的变量默认为 Int
类型。如果初始值超过了其最大值,那么推断为 Long
类型。
如需显式指定 Long
型值,请在该值后追加 L
后缀。
val one = 1 // 默认是Int类型
val threeBillion = 3000000000 // 超过了Int最大值默认是Long类型
val oneLong = 1L // 数字后面显示加L,表示声明Long类型
val oneByte: Byte = 1
浮点数
对于浮点数,Kotlin 提供了 Float
与 Double
类型。 两种浮点类型的十进制位数(即可以存储多少位十进制数)不同。 Float
(单精度),而 Double
(双精度)。
对于以小数初始化的变量,编译器会默认为 Double
类型。 如需将一个值显式指定为 Float
类型,请添加 f
或 F
后缀。 如果这样的值包含多于 6~7 位十进制数,那么会将其四舍五入,只保留7位数。
val pi = 3.14 // Double
val e = 2.7182818284 // Double
val eFloat = 2.7182818284f // Float,实际值为 2.718282
数字类型转换
在Java中是有隐试转换的,可以将一个int类型赋值给一个long类型(较小类型转成较大类型)
int e = 10;
long f = e; // implicit conversion
Kotlin中由于不同的表示方式,较小类型并不是较大类型的子类型,较小的类型不能隐式转换为较大的类型。 这意味着在不进行显式转换的情况下我们不能把 int 类型值赋给一个 long类型的变量。
val e: Int = 10
val f: Long = e // implicitness not allowed
如果需要进行转换,可以使用显式转换,如下方法:
val e: Int = 10
val f: Long = e.toLong()
println(f) // 输出结果是: 10
每种数据类型都有下面的这些方法,可以转化为其它的类型:
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char
有些情况下也是可以使用自动类型转化的,前提是可以根据上下文环境推断出正确的数据类型而且数学操作符会做相应的重载。例如下面是正确的:
val l = 1L + 3 // Long + Int => Long
println(l) // 输出结果是: 4
比较两个数字
Kotlin 中没有基础数据类型,只有封装的数字类型,你每定义的一个变量,其实 Kotlin 帮你封装了一个对象,这样可以保证不会出现空指针。数字类型也一样,所有在比较两个数字的时候,就有比较数据大小和比较两个对象是否相同的区别了。
在 Kotlin 中,三个等号 ===
表示比较对象地址,两个 ==
表示比较两个值大小。
val a: Int = 10000
println(a === a) // true,值相等,对象地址相等
//经过了装箱,创建了两个不同的对象
val boxedA: Int? = a
val anotherBoxedA: Int? = a
//虽然经过了装箱,但是值是相等的,都是10000
println(boxedA === anotherBoxedA) // false,值相等,对象地址不一样
println(boxedA == anotherBoxedA) // true,值相等
注意数字装箱不一定保留同一性:
val a: Int = 100
val boxedA: Int? = a
val anotherBoxedA: Int? = a
val b: Int = 10000
val boxedB: Int? = b
val anotherBoxedB: Int? = b
println(boxedA === anotherBoxedA) // true
println(boxedA == anotherBoxedA) // true
println(boxedB == anotherBoxedB) // true
println(boxedB === anotherBoxedB) // false
容易混淆的Long类型标记
数字字面值中的下划线
(自 1.1 起)你可以使用下划线使数字常量更易读:
val oneMillion = 1_000_000
val creditCardNumber = 1234_5678_9012_3456L
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010
数值常量字面
数值常量字面值有以下几种,不支持八进制:
- 十进制:
123
- Long 类型用大写
L
标记:123L
- Long 类型用大写
- 十六进制:
0x0F
- 二进制:
0b00001011
字符类型
字符用 Char
类型表示。它们不能直接当作数字,字符字面值用单引号括起来: '1'
。
val a = '1'
println(a == '1') // true
println(a == 1) // Operator '==' cannot be applied to 'Char' and 'Int' ,报错类型不兼容
我们可以显式把字符转换为 Int
数字:
val a = '1'
println('0'.toInt()) // 48
println(a.toInt()) // 49
println(a.toInt() == 1) // false ,'1'转换成Int类型后并不是直接就是1
println(a.toInt() - '0'.toInt()) // 1
特殊字符可以用反斜杠转义。 支持这几个转义序列:\t
、 \b
、\n
、\r
、\'
、\"
、\\
与 \$
。 编码其他字符要用 Unicode 转义序列语法:'\uFF00'
。
当需要可空引用时,像数字、字符会被装箱。装箱操作不会保留同一性。
字符串(String)类型
Kotlin声明字符串
val k = "Today is a sunny day"
val m = String("Today is a sunny day".toCharArray())
println(k)
println(m)
字符串的读取
和 Java 一样,字符串是不可变的。 字符串的元素——方括号 [] 语法可以很方便的获取字符串中的某个字符: s[i]
。 可以用 for 循环迭代字符串:
val s = "abcd"
println(s[1]) // b
for (c in s) {
println(c)
}
可以用 +
操作符连接字符串。这也适用于连接字符串与其他类型的值, 只要表达式中的第一个元素是字符串:
val s = "abc" + 1
println(s + "def") // abc1def
val b = 1 + "abc" //报错,第一个元素是字符串才行
在大多数情况下,优先使用字符串模板或原始字符串而不是字符串连接
比较两个字符串
val k = "Today is a sunny day"
val m = String("Today is a sunny day".toCharArray())
println(k)
println(m)
println(m === k) // 三个等号 === 表示比较对象地址
println(m == k) // 两个 == 表示比较两个值是否相同
转义字符串
Kotlin 有两种类型的字符串字面值: 转义字符串可以有转义字符, 以及原始字符串可以包含换行以及任意文本。以下是转义字符串的一个示例:
转义采用传统的反斜杠方式。
val s = "Hello, world!\n"
print(s) // 打印结果是Hello, world!,后面\n会认为是一个换行
多行字符串
Kotlin 支持三个引号 """ 扩起来的字符串,支持多行字符串,比如:
val text = """
多行字符串
多行字符串
"""
println(text) // 输出有一些前置空格
String 可以通过 trimMargin() 方法来删除多余的空白。
默认 | 用作边界前缀,但你可以选择其他字符并作为参数传入,比如 trimMargin(">")。
val text = """
多行字符串
多行字符串
"""
println(text) // 输出有一些前置空格
println(text.trimMargin()) // 前置空格删除了
println(text.trimMargin(">")) // 前置空格删除了
println(text.trimMargin("<")) // 前置空格删除了
println(text.trimIndent())
字符串模板
字符串字面值可以包含模板表达式 ,即一些小段代码,会求值并把结果合并到字符串中。 模板表达式以美元符($
)开头,由一个简单的名字构成:
val j = "I love China"
println("value of string 'j' is:$j") // value of string 'j' is:I love China
println("Length of string 'j' is:${j.length}") // Length of string 'j' is:12
System.out.printf("Length of string 'j' is: %d\n", j.length) // Length of string 'j' is: 12
val i = 10
val s = "i = $i" // 求值结果为 "i = 10"
println(s)
或者用花括号括起来的任意表达式:
val s = "abc"
println("$s.length is ${s.length}") // 输出“abc.length is 3”
原生字符串和转义字符串内部都支持模板。 如果你需要在原生字符串中表示字面值 $ 字符(它不支持反斜杠转义),你可以用下列语法:
val price = """
${'$'}9.99
"""
println(price) // 求值结果为 $9.99
布尔类型
布尔用 Boolean
类型表示,它有两个值:true 与 false。
若需要可空引用布尔会被装箱。
内置的布尔运算有:
||
– 短路逻辑或&&
– 短路逻辑与!
- 逻辑非
无符号类型
val oneMillion: UInt = 1_000_000u
val creditCardNumber: ULong = 1234_5678_9012_3456u
// val socialSecurityNumber: ULong = -1234_5678_9012_3456u // 无符号类型不能生命负数
println(oneMillion) // 输出结果:1000000
println(creditCardNumber) // 输出结果:1234567890123456
println(socialSecurityNumber) // 输出结果:999999999