# 基本数据类型

原始的、基本的数据类型，用于表示和操作最基本的数据

1. 数字类型
2. 布尔类型
3. 字符串类型

与 Java 基本类型相对应，Kotlin 也有 8 种基本数据类型。

* 整数类型：Byte、Short、Int、Long，Int 是默认类型
* 浮点类型：Float、Double，Double是默认类型
* 字符类型：Char
* 布尔类型：Boolean

Kotlin 中去掉了原始类型，只有包装类型，编译器在编译代码的时候，会自动优化性能，把对应的包装类型拆箱为原始类型。

## 数字类型

与Java相同，Kotlin也提供了四种整型两种浮点型，且范围也与Java一致。

整型：

| 类型    | 大小（比特数） | 最小值                               | 最大值                                 |
| ----- | ------- | --------------------------------- | ----------------------------------- |
| 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) |

浮点型：

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

### 数字类型之间的相互转换

在Kotlin中，较小的类型不可以转换为较大的类型，一下代码会报错：

```kotlin
val b: Byte = 1 // OK, 字面值是静态检测的
val i: Int = b // 错误 Type mismatch.
```

这是因为，在Kotlin中`==`号会被编译为`equals()`方法进行比较，也就是说，Kotlin的`==`操作符可以被重载与定义。

因为Byte与Int的equals方法，会首先比较类型，再比较值，故编译器限制了不同类型的数字不可进行直接比较，也不进行隐式子转换。

故Kotlin中，为每个数字类型提供了如下的方法，用于转换为其他类型：

* `toByte(): Byte`
* `toShort(): Short`
* `toInt(): Int`
* `toLong(): Long`
* `toFloat(): Float`
* `toDouble(): Double`
* `toChar(): Char`

> Char类型实际也是数字类型

### 数字类型算术运算

支持的运算符有 `+` `-` `*` `/` `%`，kotlin也支持运算符重载。

```kotlin
// 整数除法
val x = 5 / 2
//println(x == 2.5) // ERROR: Operator '==' cannot be applied to 'Int' and 'Double'
println(x == 2)

// val x = 5L / 2
println(x == 2L)

// 如果返回浮点数，需要将运算的两个数字之一转换为浮点类型
val x = 5 / 2.toDouble()
println(x == 2.5)
```

### 数字类型位运算

位运算只支持`Int`和`Long`两种类型，在这两个类型中，提供了如下方法进行位运算：

* `shl(bits)` – 有符号左移
* `shr(bits)` – 有符号右移
* `ushr(bits)` – 无符号右移
* `and(bits)` – 位与
* `or(bits)` – 位或
* `xor(bits)` – 位异或
* `inv()` – 位非

位运算只提供了相关的方法，并没有提供位运算符，但是可以使用中缀方式调用具名函数，例如：

```kotlin
val x = (1 shl 2) and 0x000FF000
```

### 数字类型比较运算

1. 相等性检测：`==`、`!=`
2. 比较大小：`a < b`、 `a > b`、 `a <= b`、 `a >= b`
3. 区间实例以及区间检测：`a..b`、 `x in a..b`、 `x !in a..b`

NaN代表非数字，他在使用比较运算符时比较特殊，总是返回false：

* `Double.NaN == Double.NaN` false
* `Double.NaN > Double.POSITIVE_INFINITY` false
* `Double.NaN < Double.POSITIVE_INFINITY` false
* `Double.NaN > Double.NEGATIVE_INFINITY` false
* `Double.NaN < Double.NEGATIVE_INFINITY` false

另外，`-0.0 == 0.0` 为true

## 字符类型、字符串类型

### 字符类型的标识

字符型通常用于表示单个的字符，字符型值必须使用单引号`'`括起来。 Kotlin 语言使用 16 位的 Unicode 字符集作为编码方式，而 Unicode 被设计成支持世界上所有书面语言的字符，包括中文字符，因此 Kotlin 程序支持各种语言的字符。

字符型值有如下 3 种表示形式 。

1. 直接通过单个字符来指定字符型值，例如 `'A'`、 `'9'` 等。
2. 通过转义字符表示特殊字符型值，包含`\t`、 `\b`、`\n`、`\r`、`\'`、`\"`、`\\` 与 `\$`。
3. 直接使用 Unicode值来表示字符型值，格式是`'\uXXXX'`，其中 XXXX 代表一个十六进制的整数，例如`'\uFF00'`。

字符类型与数字类型相同，提供了转换为其他数字类型的方法，可以使用上述的方法将Char转换为其他数字类型。

### 转义字符串与原始字符串

* 双引号包裹的转义字符串，会对转义字符转义
* 三个双引号包裹的原始字符串（多行字符串），不会对转移字符转义

```kotlin
val str1 = "abc\ndef"
val str2 = """
    abc\n
    def
""".trimIndent() // trimIndent 是去除每行的缩进， trimMargin函数则是用来去除前导空格

println(str1)
println(str2)
```

运行结果：

```
abc
def
abc\n
def
```

### 字符与字符串的转换

同java类似，字符串是由字符数组组成，如果想要取出字符串中指定位置的字符可以：

```kotlin
fun main() {
    val str = "Hello, Kotlin!"
    val index = 7
    val char = str[index]
    println("Character at index $index is $char")
}
```

如果要将字符数组转换为字符串，可以使用String的构造：

```kotlin
val charArray = charArrayOf('H', 'e', 'l', 'l', 'o')
val str = String(charArray)
println(str) // 输出：Hello
```

### 字符串拼接

应该优先使用字符串模板，而不是拼接。在Kotlin中，使用 `+` 进行字符串拼接：

```kotlin
val s = "abc" + 1
println(s + "def")
```

### 字符串模板

此外，Kotlin的字符串默认支持字符串模板：

```kotlin
val name = "张三"
val str1 = "你好${name}"
val str2 = """
    你好
    $name
""".trimIndent()

println(str1)
println(str2)
```

输出结果：

```
你好张三
你好
张三
```

## 布尔型

与Java一致，提供`true`和`false`两种值，不能用0和1替代。若需要可空引用布尔会被装箱。

内置的布尔运算包含：

* `||` 短路逻辑或
* `&&` 短路逻辑与
* `!` 逻辑非
