Kotlin 基本数据类型

从这篇文章开始,我们将深入学习 Kotlin 常见的几大基本数据类型,比如整数类型、浮点数类型、字符类型、布尔类型等。在深入之前,会先从整体上认识下 Kotlin 类型系统的划分,然后 Kotlin 中的基本类型充当其中什么角色,以及它和 Java 中基本数据类型有什么区别。

1. Kotlin 类型系统

在 Kotlin 中类型系统主要分为两大类 : 基本类型和其他基本类型,但是需要注意的是与 Java 不同,Kotlin 并不区分基本数据类型和它的包装类,然后基本数据类型还可以分为: 非空基本类型和可空基本类型

图片描述

Kotlin 中的系统类型划分

在 Kotlin 中一切皆是对象,那么从某种意义上来说我们可以再任何变量对象上调用它的成员函数与属性。而在 Java 中基本数据类型(int,double,long等)不是一个类。在 Kotlin 中基本数据类型(Int,Double,Long等)它们看起来更像是一个普通的类。所以它也不需要像 Java 的 int 一样有对应的包装器类 Integer,Kotlin 的基本数据类型没有对应的包装器类。

图片描述

Kotlin 中的基本数据类型详细划分

上图是 Kotlin 中的基本数据类型详细划分,下面我们来一一看下这几种数据类型:

2. 数字类型

2.1 整数类型

Kotlin 中提供一组表示整数数字的内置类型,主要有四种,下面是一张表格表示它们各自取值范围:

类型 大小(占用比特数) 最小值 最大值
Byte 8 -128 127
Short 16 -32768 32767
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
val number = 100 //默认是 Int 类型
val bigNumber = 8000000000 //超过 Int 最大值默认是 Long 类型
val longNumber = 20L //数字后面显式加L,表示声明 Long 类型
val byteNumber: Byte = 1

Tips:所有未超出 Int 最大值的整型值初始化的变量都默认为Int类型,如果初始值超过了其最大值,那么推断为Long类型。在数字值后面显式添加L表示一个Long类型

2.2 浮点数类型

Kotlin 中提供了 FloatDouble 两种类型来分别表示单精度和双精度的浮点数类型。

类型 大小(占用比特数) 有效数字比特数 指数比特数 十进制位数
Float 32 24 8 6-7
Double 64 53 11 15-16

一起来看下几个例子:

val pi = 3.1415926 //默是Double类型
val doubleNumber = 1.23343434343 //默认是Double类型
val floatNumber = 2.3423344378f//尾部加f或F显式表示这是一个Float类型的浮点数

Kotlin 对于默认小数的推断是Double类型。如果需要显式将一个小数指定为Float类型需要在数值尾部加入fF。由于Float类型十进制位数是6~7,所以上述例子中floatNumber实际值大小为2.3423344,后面就会出现进度丢失舍弃。

在 Kotlin 中还有一点与 Java 不同的是,Kotlin 中数字不存在隐式的拓宽转换。比如一个函数参数为Double 的函数只能接收 Double 类型,不能接收 FloatInt 或者其他数字类型。

图片描述
图片描述

2.3 数字常量

在 Kotlin 支持数字的十进制、二进制、十六进制的表示,但是注意 Kotlin 不支持八进制的表示

进制表示 十进制 二进制 十六进制
示例 100 0b00001001 0x0F

在 Kotlin 为了使得数字常量更易可读,可以使用下划线将数字隔开。

val bigNumber = 3_000_000_000
val bytesNumber = 0b11010010_01101111_0001001_10001000
val hexNumber = 0xFF_EF_D7_3F

2.4 数字类型强制转换

在 Kotlin 中与 Java 不同是通过调用 toInt、toDouble、toFloat 之类函数来实现数字类型的强制转换的。

类型 强转函数
Byte toByte()
Short toShort()
Int toInt()
Long toLong()
Float toFloat()
Double toDouble()
Char toChar()

缺乏隐式类型转换很少会引起注意,因为类型会从上下文推断出来,而算术运算会有重载做适当转换,例如:

val number = 20L + 40 // Long + Int => Long

2.5 数字运算

2.5.1 四则运算

除法/

val number = 3 / 2
println(number) // 输出 1

val floatNumber = 3 / 2.toDouble()
println(number) // 输出 1.5

乘法*

val number = 3 * 2
println(number) // 输出 6

加法+

val number = 3 + 2
println(number) // 输出 5

减法-

val number = 3 - 2
println(number) // 输出 1

取余%

val number = 3 % 2
println(number) // 输出 1
2.5.2 位运算

Kotlin 中的位运算和 Java 不同的是没有用特殊符号来表示,可以采用了中缀函数方式调用具名函数。

  • shl(bits) – 有符号左移;
  • shr(bits) – 有符号右移;
  • ushr(bits) – 无符号右移;
  • and(bits) – 位
  • or(bits) – 位
  • inv() – 位
  • xor(bits) – 位异或
val number = (3 shr 4) and 0x000EF000

3. 字符类型

在 Kotlin 中字符用 Char 类型表示。并且不能像 Java 一样可以直接当作数字:

fun testChar(char: Char) {
    if(char == 4) {...}//此处会提示类型不匹配的异常
}

字符的值用单引号括起来: '1'。 特殊字符可以用反斜杠转义。 支持这几个转义序列:tbnr'"\$。 编码其他字符要用 Unicode 转义序列语法:'uFF00'

虽然不能直接把它当作数字来用,但是我们可以通过decimalDigitValue函数将字符转换成数字,注意可空类型 Char? 类型会存在装箱操作

fun decimalDigitValue(c: Char): Int {
    if (c !in '0'..'9')
        throw IllegalArgumentException("Out of range")
    return c.toInt() - '0'.toInt() // 显式转换为数字
}

4. 布尔类型

在 Kotlin 使用Boolean表示布尔类型,它只有两个值 truefalse。注意可空类型Boolean?类型会存在装箱操作。

val isVisible: Boolean = false

5. 数组类型

5.1 Array 数组

在 Kotlin 中数组使用Array这个类来辨识,它定义了 getset 函数(按照运算符重载约定这会转变为 [])以及 size 属性,以及一些其他有用的成员函数:

public class Array<T> {
    /**
     * Creates a new array with the specified [size], where each element is calculated by calling the specified
     * [init] function.
     *
     * The function [init] is called for each array element sequentially starting from the first one.
     * It should return the value for an array element given its index.
     */
    public inline constructor(size: Int, init: (Int) -> T)

    /**
     * Returns the array element at the specified [index]. This method can be called using the
     * index operator.
     * ```
     * value = arr[index]
     * ```
     *
     * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS
     * where the behavior is unspecified.
     */
    public operator fun get(index: Int): T

    /**
     * Sets the array element at the specified [index] to the specified [value]. This method can
     * be called using the index operator.
     * ```
     * arr[index] = value
     * ```
     *
     * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS
     * where the behavior is unspecified.
     */
    public operator fun set(index: Int, value: T): Unit

    /**
     * Returns the number of elements in the array.
     */
    public val size: Int

    /**
     * Creates an iterator for iterating over the elements of the array.
     */
    public operator fun iterator(): Iterator<T>
}

我们可以使用库函数 arrayOf() 来创建一个数组并传递元素值给它,这样 arrayOf(1, 2, 3) 创建了 array [1, 2, 3]。 或者,库函数 arrayOfNulls() 可以用于创建一个指定大小的、所有元素都为空的数组。

另一个选项是用接受数组大小以及一个函数参数的 Array 构造函数,用作参数的函数能够返回给定索引的每个元素初始值:

//创建一个 Array<String> 初始化为 ["0", "1", "4", "9", "16", "25", "36", "49", "64", "81"]
val asc = Array(10) { i -> (i * i).toString() }
asc.forEach { println(it) }

5.2 原生类型数组

在Kotlin中也有无装箱开销的专门的类来表示原生类型数组: ByteArrayShortArrayIntArray 等等。这些类与 Array 并没有继承关系,但是它们有同样的方法和属性。

val intArray = intArrayOf(1, 2, 3, 4, 5)// 使用intArrayOf函数创建并初始化一个IntArray  [1, 2, 3, 4, 5]

val intArr1 = IntArray(5) //创建一个长度为5的空的IntArray

val intArr2 = IntArray(5) { 100 } //创建一个长度为5的值全为100的IntArray [100, 100, 100, 100, 100]

val intArr3 = IntArray(5) { it * 2 } //注意这里it是它索引下标值,所以这是创建一个长度为5的IntArray [0, 2, 4, 6, 8]

6. 字符串类型

在 Kotlin 中字符串用 String 类型表示。字符串是不可变的。 字符串的元素——字符可以使用索引运算符访问: s[i]。 可以用 for 循环迭代字符串:

for(char in str) {
    println(char)
}

和 Java 一样,Kotlin 可以用 + 操作符连接字符串。这也适用于连接字符串与其他类型的值, 只要表达式中的第一个元素是字符串,但是 Kotlin 中有字符串模板,大部分情况下建议使用字符串模板来替代+拼接字符串。

val age = 28
println("I am " + age + "years old!")
println("I am $age years old!")

6.1 字符串的值

Kotlin 有两种类型的字符串字面值:转义字符串可以有转义字符, 以及原始字符串可以包含换行以及任意文本。以下是转义字符串的一个示例:

val s = "Hello, world!n"

转义采用传统的反斜杠方式。

字符串使用三个引号(""")分界符括起来,内部没有转义并且可以包含换行以及任何其他字符:

val text = """
    for (c in "foo")
        print(c)
"""

还可以通过 trimMargin() 函数去除前导空格:

val text = """
    |Tell me and I forget.
    |Teach me and I remember.
    |Involve me and I learn.
    |(Benjamin Franklin)
    """.trimMargin()

6.2 字符串模板

字符串字面值可以包含模板表达式 ,即一些小段代码,会求值并把结果合并到字符串中。 模板表达式以美元符($)开头,由一个简单的名字构成:

val number = 100
println("The Result is $number")

或者用花括号${}括起来的任意表达式:

val text = "This is Text"
println("Text length is ${text.length}")

字符串与转义字符串内部都支持模板。 如果你需要在原始字符串中表示字面值 $ 字符(它不支持反斜杠转义),你可以用下列语法:

val price = "${'$'}9.99"

7. 小结

到这里有关 Kotlin 基本类型就阐述完毕了,下一篇文章我们将进入Kotlin中的条件选择、循环分支控制相关知识点。

图片描述