kotlin
中有以下基本数据类型
类别 | 基本数据类型 |
---|---|
整数(Integers) | Byte , Short , Int , Long |
无符号整数(Unsigned integers) | UByte , UShort , UInt , ULong |
浮点数(Floating-point numbers) | Float , Double |
布尔值(Booleans) | Boolean |
字符(Characters) | Char |
字符串(Strings) | String |
在声明变量的时候指定变量类型
fun main(){
val d: Int // 声明变量及数据类型,不赋值
d = 3 // 赋值
val e: String = "hello" // 声明变量及数据类型并赋值
println(d) // 3
println(e) // hello
}
在 kotlin
中,一切都是对象,可以在任何变量上调用成员函数和属性。虽然某些类型在运行时具有优化的内部表示形式作为基元值(例如数字、字符、布尔值等),但它们的外观和行为像常规类一样
类型 | 大小 (bits) | 最小值 | 最大值 |
---|---|---|---|
Byte | 8 | -128 | 127 |
Short | 16 | -32768 | 32767 |
Int | 32 | -2,147,483,648 (-231) | 2,147,483,647 (231 - 1) |
Long | 64 | -9,223,372,036,854,775,808 (-263) | 9,223,372,036,854,775,807 (263 - 1) |
如果没有显示的指定数据类型,kotlin
会自动判断为最小的数据类型。如果想要指定类型,可以在值后边添加后缀
fun main(){
val one = 1 // Int
val threeBillion = 3000000000 // Long
val oneLong = 1L // Long
val oneByte: Byte = 1
}
kotlin
浮点数符合IEEE 754 标准
,有单精度Float
和双精度Double
两种类型
类型 | 大小 (bits) | 有效位数(Significant bits) | 指数位数(Exponent bits) | 十进制数字(Decimal digits) |
---|---|---|---|---|
Float | 32 | 24 | 8 | 6-7 |
Double | 64 | 53 | 11 | 15-16 |
kotlin
默认浮点数为Double
类型,如果想要定义Float
类型变量需要添加后缀。浮点数不能接收整数类型
fun main(){
val pi = 3.14 // Double
// val one: Double = 1 // Error: type mismatch
val oneDouble = 1.0 // Double
val e = 2.7182818284 // Double
val eFloat = 2.7182818284f // Float, 2.7182817 ,如果小数位数超长,则进行四舍五入(这是因为计算机在存储浮点数时,使用的是二进制(base-2)表示法,而不是我们常用的十进制(base-10)表示法。在二进制表示法中,无法精确地表示大多数十进制小数。)
}
kotlin
数据类型不支持隐式转换
,也就是说不能把一个较小的值自动转换成较大类型,需要手动转换才可以
fun main(){
fun printDouble(d: Double) { print(d) }
val i = 1
val d = 1.0
val f = 1.0f
printDouble(d)
// printDouble(i) // Error: Type mismatch
// printDouble(f) // Error: Type mismatch
printDouble(i.toDouble())
printDouble(f.toDouble())
}
数字类型支持转换成其他类型
大多数情况下会根据上下文进行推断,并且算术运算会重载以进行适当的转换
val l = 1L + 3 // Long + Int => Long
L
表示:123L为了方便阅读可以使用分隔符
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
在Kotlin中,==
和===
是两种不同的比较运算符:
==
用于比较两个变量的值是否相等。例如,如果我们有两个变量a和b,并且它们的值都是5,那么a == b
将返回true。===
用于比较两个变量是否指向同一个对象。这被称为引用相等性。例如,如果我们有两个变量a和b,并且它们都指向同一个对象,那么a === b
将返回true
。但是,如果a和b指向的是两个不同的对象,即使这两个对象的值相同,a === b
也会返回false。对于Byte
类型来说,上边的说法不成立,因为在JVM
中。JVM对-128到127之间的整数应用了内存优化,所有指向这些值的对象为同一个对象
fun main(){
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(boxedB === anotherBoxedB) // false
println(boxedB == anotherBoxedB) // true
}
数字支持标志运算符+
、-
、*
、/
、%
整数与整数做除法,得到一个整数,小数部分被舍弃
val x = 5 / 2
//println(x == 2.5) // ERROR: Operator '==' cannot be applied to 'Int' and 'Double'
println(x == 2)
可以显示的将其中任意数字转成浮点数
val x = 5 / 2.toDouble()
println(x == 2.5)
Kotlin为整数提供了一组位运算。它们直接在二进制级别上操作数字的表示位。位运算由可以以中缀形式调用的函数表示。它们只能应用于Int和Long:
val x = (1 shl 2) and 0x000FF000
这些操作允许我们直接操作整数的二进制表示,这在某些情况下(如硬件编程或性能关键代码)可能非常有用
本节讨论的浮点数操作包括:
a == b
和 a != b
a < b
,a > b
,a <= b
,a >= b
a…b
,x in a…b
,x !in a…b
当操作数 a 和 b 静态地被知道为 Float
或 Double
或它们的可空对应物(类型被声明或推断或是智能转换的结果),它们和它们形成的范围上的操作遵循IEEE 754
浮点算术标准。
然而,为了支持通用用例和提供全序,对于不是静态类型为浮点数的操作数,行为是不同的。例如,Any
,Comparable<…>
,或 Collection
类型。在这种情况下,操作使用 Float
和 Double
的 equals
和 compareTo
实现。因此:
NaN
被认为等于它自己NaN
被认为大于任何其他元素,包括 POSITIVE_INFINITY
-0.0
被认为小于 0.0
这里有一个例子,展示了静态类型为浮点数的操作数(Double.NaN)和非静态类型为浮点数的操作数(listOf(T))之间的行为差异
在Kotlin编程语言中,Double.POSITIVE_INFINITY 是一个常量,它表示 Double 类型的正无穷大值
fun main() {
// 操作数静态类型为浮点数
println(Double.NaN == Double.NaN) // false
// 操作数非静态类型为浮点数
// 所以 NaN 等于它自己
println(listOf(Double.NaN) == listOf(Double.NaN)) // true
// 操作数静态类型为浮点数
println(0.0 == -0.0) // true
// 操作数非静态类型为浮点数
// 所以 -0.0 小于 0.0
println(listOf(0.0) == listOf(-0.0)) // false
// 对集合中元素进行排序结果不一定与单个比较结果相同
println(listOf(Double.NaN, Double.POSITIVE_INFINITY, 0.0, -0.0).sorted()) // [-0.0, 0.0, Infinity, NaN]
println(Double.NaN < Double.POSITIVE_INFINITY) // false
println(Double.NaN > Double.POSITIVE_INFINITY) // false
println(Double.NaN == Double.POSITIVE_INFINITY) // false
}
Boolean
类型表示布尔对象,它可以有两个值:true
和 false
Boolean
有一个可为空的对应物 Boolean?
,它也可以有 null
值。
布尔值的内置操作包括:
||
- 或(逻辑或)&&
- 与(逻辑与)!
- 非(逻辑非)||
和 &&
是懒惰的工作方式。
fun main() {
val myTrue: Boolean = true
val myFalse: Boolean = false
val boolNull: Boolean? = null
println(myTrue || myFalse) // true
println(myTrue && myFalse) // false
println(!myTrue) // false
}
字符由 Char
类型表示。字符字面量用单引号表示:‘1’
。
特殊字符以转义反斜杠 \
开头。支持以下转义序列:
\t
– 制表符\b
– 退格\n
– 新行(LF)\r
– 回车(CR)'
– 单引号"
– 双引号\
– 反斜杠$
– 美元符号要编码任何其他字符,使用 Unicode
转义序列语法:‘\uFF00’
。
fun main() {
val aChar: Char = 'a'
println(aChar) // a
println('\n') // 输出空行
println("\$_9.99") // $_9.99
println('\uFF00')
}
如果字符变量的值是数字,你可以使用
digitToInt()
函数将其显式转换为Int
数字。
在 JVM 上:像数字一样,当需要可为空引用时,字符会被装箱。装箱操作不保留身份。
字符串在kotlin
中 使用String
类型表示,用双括号"
包裹
字符串
的内容是字符
,可以使用索引操作访问
fun main() {
val str = "abcd 123"
for (c in str) {
println(c)
}
}
字符串初始化后,值不能改变。所有对字符串的操作都应该使用新的对象接收
fun main() {
var str = "abcd"
// 变大写
println(str.uppercase()) // ABCD
println(str) // abcd
}
字符串拼接使用+
。字符串可以与其他类型的值拼接,拼接完成后还是字符串类型
fun main() {
val s = "abc" + 1
println(s + "def") // abc1def
}
拼接字符串建议使用字符串模板或多行字符串
字符串模板 字符串字面量可能包含模板表达式 - 代码片段,这些代码片段被求值,其结果被连接到字符串中。模板表达式以$
开始,由一个名称组成:
fun main(){
val i = 10
println("i = $i") // Prints "i = 10"
}
或者用${}
包裹的表达式
fun main(){
val s = "abc"
println("$s.length is ${s.length}") // Prints "abc.length is 3"
}
多行字符串可以包含换行符在内的任意文本。它由三个引号'''
分隔
fun main(){
val text2 = """
for (c in "foo")
print(c)
"""
println(text2)
/**
* for (c in "foo")
* print(c)
*/
}
可以使用trimMargin()
删除字符串前的空格
fun main() {
val text = """
|Tell me and I forget.
Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()
println(text)
/*
*
*Tell me and I forget.
* Teach me and I remember. --> 行前有空格
*Involve me and I learn.
*(Benjamin Franklin)
*
* */
}
文本中
|
可以替换成其他符号,如>
多行字符串不支持转义符
fun main() {
// val price = """
// \$_9.99 // Unresolved reference: _9
// """
val price = """
${'$'}_9.99
""" // 特殊字符需要使用${}包裹
println(price) // $_9.99
}