ZetCode

Kotlin 数据类型

最后修改于 2024 年 1 月 29 日

本文涵盖 Kotlin 数据类型,包括布尔值、数字和字符串。

数据类型

一个 数据类型 是一组值以及对这些值允许的操作。

Kotlin 是一种强静态类型编程语言。每个变量和每个表达式都有一个在编译时已知的类型。Kotlin 也是一种强类型语言,因为类型限制了变量可以保存的值或表达式可以产生的值,限制了对这些值的支持操作,并决定了操作的含义。强静态类型有助于在编译时检测错误。Kotlin 不支持类型之间的隐式转换。

注意: 很多时候,我们不必显式指定变量的数据类型;Kotlin 使用类型推断来确定数据类型。

像 Ruby 或 Python 这样的动态类型语言中的变量可以随时间接收不同的数据类型。在 Kotlin 中,一旦变量被声明为某种数据类型,它就不能保存其他数据类型的值。

Kotlin 具有以下基本数据类型

还有一个特殊的 null 类型,表示一个不存在的值。

Kotlin 布尔值

我们的世界中内建了一种二元性。有天堂和地球,水和火,阴和阳,男人和女人,爱和恨。在 Kotlin 中,boolean 数据类型是一种基本数据类型,有两个值之一:truefalse

假设我们想为一个孩子选择一个名字。

boolean_type.kt
package com.zetcode

import kotlin.random.Random

fun main() {

    var name = ""
    val male: Boolean = Random.nextBoolean()

    if (male) {
        name = "Robert"
    }

    if (!male) {
        name = "Victoria"
    }

    println("We will use name $name")

    println(9 > 8)
}

该程序使用随机数生成器来模拟我们的情况。

var name = ""

我们定义一个空的 name 变量。我们没有显式指定数据类型;Kotlin 使用类型推断来获取适当的数据类型。在我们的例子中,它是 String

val male: Boolean = Random.nextBoolean()

Random 类用于生成随机数。nextBoolean 方法随机返回一个布尔值。

if (male) {
    name = "Robert"
}

如果布尔变量 male 等于 true,我们将 name 变量设置为 "Robert"。if 关键字与布尔值一起使用。

if (!male) {
    name = "Victoria"
}

如果随机生成器选择 false,那么我们将 name 变量设置为 "Victoria"。

println(9 > 8)

关系运算符的结果是一个布尔值。这行代码在控制台上打印 true。

Kotlin 整数

整数是实数的子集。它们没有小数或小数部分。整数属于集合 Z = {..., -2, -1, 0, 1, 2, ...} 整数是无限的。

计算机实际上只能使用整数值的子集,因为计算机的容量是有限的。整数用于计数离散的实体。我们可以有 3、4 或 6 个人,但我们不能有 3.33 个人。我们可以有 3.33 公斤,4.564 天或 0.4532 公里。

类型 大小 范围
Byte 8 位 -128 到 127
Short 16 位 -32,768 到 32,767
Int 32 位 -2,147,483,648 到 2,147,483,647
Long 64 位 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
表:Kotlin 中的整数类型

整数的使用取决于我们所执行的任务类型。然后我们可以使用 Byte 类型来表示一个变量,该变量存储一个女人所生的孩子的数量。经过验证的最年长的人死于 122 岁,因此我们可能会为 age 变量选择至少 Short 类型。这将为我们节省一些内存。

所有使用不超过 Int 最大值的整数值初始化的变量都具有推断类型 Int。如果初始值超过此值,则类型为 Long。要显式指定 Long 值,请在值后附加后缀 L。

当我们使用整数时,我们处理离散项。例如,我们可以使用整数来计算苹果的数量。

apples.kt
package com.zetcode

fun main() {

    val baskets: Int = 16
    val applesInBasket: Int = 24

    val total = baskets * applesInBasket

    println("There are total of $total apples")
}

在我们的程序中,我们计算苹果的总数。我们使用乘法运算。

val baskets: Int = 16
val applesInBasket: Int = 24

篮子的数量和每个篮子里的苹果数量都是整数值。

val total = baskets * applesInBasket

将这些值相乘,我们也会得到一个整数。

There are total of 384 apples

整数可以用 Kotlin 中的三种不同的表示法指定:十进制、十六进制和二进制。十进制数通常像我们知道的那样使用。十六进制数以 0x 字符开头,后跟十六进制数。二进制数以 0b 开头,后跟二进制数(零和一)。

integer_notations.kt
package com.zetcode

fun main() {

    val n1 = 31
    val n2 = 0x31
    val n3 = 0b1001

    println(n1)
    println(n2)
    println(n3)
}

我们有四个整数变量。每个变量都分配了一个具有不同整数表示法的值。

val n1 = 31
val n2 = 0x31
val n3 = 0b1001

第一个是十进制,第二个是十六进制,第三个是二进制。

31
49
9

我们看到了程序的输出。

大数字难以阅读。如果我们有一个像 245342395423452 这样的数字,我们会发现很难快速阅读它。因此,可以用下划线分隔整数。

下划线不能用于数字的开头或结尾,不能与浮点字面量中的小数点相邻,也不能在 FL 后缀之前使用。

underscores.kt
package com.zetcode

fun main() {

    val a = 23482345629L
    val b = 23_482_345_629L

    println(a == b)
}

此代码示例演示了 Kotlin 中下划线的使用。

val a = 23482345629L
val b = 23_482_345_629L

我们有两个相同的长数字。在第二个数字中,我们分隔数字中的每三个数字。比较这两个数字,我们得到一个布尔值 true。L 后缀告诉编译器我们有一个长数字字面量。

Kotlin 整数最小/最大值

整数数据类型将其最小和最大值作为常量提供。

min_max.kt
package com.zetcode

fun main() {

    val a: Byte = Byte.MIN_VALUE
    val b: Byte = Byte.MAX_VALUE
    println("Min byte value: $a")
    println("Max byte value: $b")

    val c: Short = Short.MIN_VALUE
    val d: Short = Short.MAX_VALUE
    println("Min short value: $c")
    println("Max short value: $d")

    val e: Int = Int.MIN_VALUE
    val f: Int = Int.MAX_VALUE
    println("Min integer value: $e")
    println("Max integer value: $f")

    val g: Long = Long.MIN_VALUE
    val h: Long = Long.MAX_VALUE
    println("Min long integer value: $g")
    println("Max long integer value: $h")
}

该示例打印 ByteShortIntLong 类型的最小和最大值。

Min byte value: -128
Max byte value: 127
Min short value: -32768
Max short value: 32767
Min integer value: -2147483648
Max integer value: 2147483647
Min long integer value: -9223372036854775808
Max long integer value: 9223372036854775807

Kotlin BigInteger

ByteShortIntLong 类型用于表示固定精度数字。这意味着它们可以表示有限数量的整数。long 类型可以表示的最大整数是 9223372036854775807。如果我们要处理更大的数字,我们必须使用 java.math.BigInteger 类。它用于表示不可变的任意精度整数。任意精度整数仅受可用计算机内存量的限制。

big_integers.kt
package com.zetcode

import java.math.BigInteger

fun main() {

    println(Long.MAX_VALUE)

    val b = BigInteger("92233720368547758071")
    val c = BigInteger("52498235605326345645")

    val a = b.multiply(c)

    println(a)
}

java.math.BigInteger 类的帮助下,我们乘以两个非常大的数字。

println(Long.MAX_VALUE)

我们打印可以由 Long 类型表示的最大整数值。

val b = BigInteger("92233720368547758071")
val c = BigInteger("52498235605326345645")

我们定义了两个 BigInteger 对象。它们都保存比 Long 类型可以保存的值更大的值。

val a = b.multiply(c)

使用 multiply 方法,我们乘以这两个数字。请注意,BigInteger 数字是不可变的。该操作返回一个新值,我们将其分配给一个新变量。

println(a)

计算出的整数将打印到控制台。

9223372036854775807
4842107582663807707870321673775984450795

Kotlin 算术溢出

算术溢出是一种当计算产生的结果在幅度上大于给定的寄存器或存储位置可以存储或表示的结果时发生的条件。

overflow.kt
package com.zetcode

fun main() {

    var a: Byte = 126

    println(a)
    a++

    println(a)
    a++

    println(a)
    a++

    println(a)
}

在此示例中,我们尝试分配一个超出数据类型范围的值。这会导致算术溢出。

126
127
-128
-127

当发生溢出时,变量将重置为负上界值。

Kotlin 浮点数

实数衡量连续量,如重量、高度或速度。浮点数表示计算机中实数的近似值。在 Kotlin 中,我们有两种原始浮点类型:FloatDoubleFloat 是一种单精度类型,它以 32 位存储数字。Double 是一种双精度类型,它以 64 位存储数字。这两种类型具有固定精度,并且不能完全表示所有实数。在我们需要处理精确数字的情况下,我们可以使用 BigDecimal 类。

对于用小数初始化的变量,编译器推断 Double 类型。要显式指定值的 Float 类型,请添加后缀 f 或 F。

假设一位 100 米短跑运动员跑了 9.87 秒。他的速度是多少公里/小时?

sprinter.kt
package com.zetcode

fun main() {

    val speed: Float

    val distance = 0.1f
    val time: Float = 9.87f / 3600

    speed = distance / time

    println("The average speed of a sprinter is $speed km/h")
}

在本例中,需要使用浮点值。float 数据类型的低精度在这种情况下不会构成问题。

val distance = 0.1f

100 米是 0.1 公里。

time = 9.87f / 3600;

9.87 秒是 9.87/60*60 小时。

val time: Float = 9.87f / 3600

为了获得速度,我们将距离除以时间。

The average speed of a sprinter is 36.474163 km/h

数字中的一个小舍入误差不会影响我们对短跑运动员速度的理解。

floatdouble 类型是不精确的。

floating_inprecision.kt
package com.zetcode

fun main() {

    val a = 0.1 + 0.1 + 0.1
    val b = 0.3

    println(a)
    println(b)

    println(a == b)
}

代码示例说明了浮点值的非精确性。

val a = 0.1 + 0.1 + 0.1
val b = 0.3

我们定义了两个 Double 值。

println(a)
println(b)

打印它们将显示一个非常小的差异。

println(a == b)

这行代码将返回 false。

0.30000000000000004
0.3
false

存在一个小误差。因此,比较运算符返回一个布尔值 false。

当我们在处理金钱、货币以及通常在商业应用中时,我们需要使用精确的数字。基本浮点类型的舍入误差是不可接受的。

counting_money.kt
package com.zetcode

fun main() {

    val c = 1.46f
    var sum = 0f

    for (i in 0..99999) {
        sum += c
    }

    println(sum)
}

1.46f 代表 1 欧元和 46 美分。我们从 100000 个这样的金额中创建一个总和。

for (i in 0..99999) {
    sum += c
}

在这个循环中,我们从 100000 个这样的金额中创建一个总和。

146002.55

计算会导致 2 欧元和 55 美分的误差。

为了避免这种边际误差,我们使用 BigDecimal 类。它用于保存不可变的任意精度有符号十进制数。

counting_money2.kt
package com.zetcode

import java.math.BigDecimal

fun main() {

    val c = BigDecimal("1.46")
    var sum = BigDecimal("0")

    for (i in 0..99999) {

        sum = sum.add(c)
    }

    println(sum)
}

我们对相同数量的钱进行相同的操作。

val c = BigDecimal("1.46")
var sum = BigDecimal("0")

我们定义了两个 BigDecimal 数字。

for (i in 0..99999) {

    sum = sum.add(c)
}

BigDecimal 数字是不可变的,因此在每个循环中,一个新对象始终分配给 sum 变量。

146000.00

在本例中,我们得到精确的值。

Kotlin 支持浮点值的科学表示法。也称为指数表示法,这是一种以标准十进制表示法书写不方便的太大或太小的数字的方法。

scientific_notation.kt
package com.zetcode

import java.math.BigDecimal
import java.text.DecimalFormat

fun main() {

    val n = 1.235E10

    val dec = DecimalFormat("#.00")
    println(dec.format(n))

    val bd = BigDecimal("1.212e-19")

    println(bd.toEngineeringString())
    println(bd.toPlainString())
}

我们使用科学表示法定义了两个浮点值。

val n = 1.235E10

这是一个 Double 类型的浮点值,以科学表示法书写。

val dec = DecimalFormat("#.00")
println(dec.format(n))

我们使用 DecimalFormat 类将我们的 double 值排列成标准十进制格式。

val bd = BigDecimal("1.212e-19")

println(bd.toEngineeringString())
println(bd.toPlainString())

BigDecimal 类将科学表示法中的浮点值作为参数。我们使用该类的两种方法以工程和纯字符串形式打印值。

12350000000.00
121.2E-21
0.0000000000000000001212

Kotlin 显式转换

Kotlin 支持数字之间的显式转换。与 Java 不同,没有隐式转换。

每个数字类型都有以下转换函数

explicit_conversion.kt
package com.zetcode

fun main() {

    val x:Long = 23_334
    val y:Int = x.toInt()

    println(x)
    println(y)
}

在示例中,我们将 Long 值转换为 Int

Kotlin 字符串和字符

String 是一种数据类型,表示计算机程序中的文本数据。Kotlin 中的字符串是一系列字符。Char 是一个单个字符。字符串用双引号括起来。

访问 Kotlin 字符串教程 了解更多关于字符串的信息。

strings_chars.kt
package com.zetcode

fun main() {

    val word = "ZetCode"

    val c: Char = word[0]
    val d: Char = word[3]

    println(c)
    println(d)
}

该程序将 Z 字符打印到终端。

val word = "ZetCode"

在这里,我们创建一个字符串变量并将其赋值为“ZetCode”值。

val c: Char = word[0]

使用 [] 数组访问符号,我们获取索引为 0 的字符。

Z
C

程序将 "ZetCode" 字符串的第一个和第四个字符打印到控制台。

Kotlin 数组

数组是一种复杂的数据类型,它处理元素的集合。可以通过索引访问每个元素。数组的所有元素必须具有相同的数据类型。

访问 Kotlin 数组教程 了解更多关于 Kotlin 中的数组的信息。

arrays.kt
package com.zetcode

fun main() {

    val numbers = IntArray(5)

    numbers[0] = 3
    numbers[1] = 2
    numbers[2] = 1
    numbers[3] = 5
    numbers[4] = 6

    val len = numbers.size

    for (i in 0 until len) {

        println(numbers[i])
    }
}

在此示例中,我们声明一个数组,用数据填充它,然后将数组的内容打印到控制台。

val numbers = IntArray(5)

我们创建一个整数数组,最多可以存储 5 个整数。所以我们有一个包含五个元素的数组,索引为 0..4。

numbers[0] = 3
numbers[1] = 2
numbers[2] = 1
numbers[3] = 5
numbers[4] = 6

在这里,我们将值分配给创建的数组。我们可以通过数组访问表示法访问数组的元素。它由数组名称后跟方括号组成。在方括号内,我们指定要访问的元素的索引。

val len = numbers.size

每个数组都有一个 size 属性,该属性返回数组中元素的数量。

for (i in 0 until len) {

    println(numbers[i])
}

我们遍历数组并将数据打印到控制台。

3
2
1
5
6

来源

Kotlin 基本类型 - 语言参考

在本文中,我们已经介绍了 Kotlin 数据类型。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已经撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出 所有 Kotlin 教程