Added kotlin guide. (WIP) (15.10.26)
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
---
|
||||
title: Типы данных
|
||||
description: Система типов Kotlin, числа, boolean, Char и отсутствие примитивов на уровне языка
|
||||
tags:
|
||||
- kotlin
|
||||
- types
|
||||
---
|
||||
|
||||
В Kotlin: статическая типизация, сильная, с выводом типов.
|
||||
|
||||
Главное отличие от Java: **на уровне языка примитивов нет**. Всё - объект, у всего есть методы.
|
||||
```kotlin
|
||||
val x: Int = 42
|
||||
println(x.toString()) // у числа есть методы
|
||||
println(42.coerceIn(0, 10)) // 10
|
||||
```
|
||||
Но в байт-коде `Int` компилируется в `int`, если это возможно - производительность не теряется. Подробнее в [Kotlin в байт-коде](../../Взаимодействие%20с%20Java/Kotlin%20в%20байт-коде.md).
|
||||
|
||||
## Иерархия типов
|
||||
```mermaid
|
||||
graph TD
|
||||
Any["Any — корень всех non-null типов"]
|
||||
Any --> Number
|
||||
Any --> Char
|
||||
Any --> Boolean
|
||||
Any --> String
|
||||
Any --> Other["классы, интерфейсы, ..."]
|
||||
Number --> Byte
|
||||
Number --> Short
|
||||
Number --> Int
|
||||
Number --> Long
|
||||
Number --> Float
|
||||
Number --> Double
|
||||
Nothing["Nothing — наследник всех типов"]
|
||||
```
|
||||
`Any`, `Unit` и `Nothing` - особые типы, им посвящена отдельная заметка: [Any, Unit, Nothing](../Базовые%20типы%20ООП/Any,%20Unit,%20Nothing.md)
|
||||
|
||||
## Числовые типы
|
||||
| Тип | Размер, бит | Диапазон |
|
||||
|---|---|---|
|
||||
| `Byte` | 8 | −128 … 127 |
|
||||
| `Short` | 16 | −32 768 … 32 767 |
|
||||
| `Int` | 32 | ≈ ±2 млрд |
|
||||
| `Long` | 64 | ≈ ±9,2 · 10¹⁸ |
|
||||
| `Float` | 32 | ≈ 6-7 значащих цифр |
|
||||
| `Double` | 64 | ≈ 15-16 значащих цифр |
|
||||
|
||||
Все наследуются от `Number`, но **не** друг от друга: `Int` не является подтипом `Long`.
|
||||
|
||||
### Литералы
|
||||
```kotlin
|
||||
val i = 42 // Int по умолчанию
|
||||
val l = 42L // Long — суффикс L
|
||||
val d = 42.0 // Double по умолчанию
|
||||
val f = 42.0f // Float — суффикс f
|
||||
val hex = 0xFF // 255
|
||||
val bin = 0b1010 // 10
|
||||
val big = 1_000_000 // подчёркивания для читаемости
|
||||
```
|
||||
Восьмеричных литералов (`017` в Java) в Kotlin **нет**.
|
||||
|
||||
## Беззнаковые типы
|
||||
`UByte`, `UShort`, `UInt`, `ULong` - то, чего в Java нет совсем.
|
||||
```kotlin
|
||||
val u: UInt = 4_000_000_000u // суффикс u
|
||||
println(UInt.MAX_VALUE) // 4294967295
|
||||
```
|
||||
Нужны редко: работа с бинарными форматами, протоколами, хешами.
|
||||
|
||||
## Boolean
|
||||
```kotlin
|
||||
val yes: Boolean = true
|
||||
val both = yes && other() // ленивые операторы, как в Java
|
||||
val eager = yes and other() // не ленивый: other() вызовется всегда
|
||||
```
|
||||
|
||||
## Char
|
||||
```kotlin
|
||||
val c: Char = 'A'
|
||||
println(c.code) // 65 — числовой код
|
||||
println(c + 1) // B — Char + Int даёт Char
|
||||
println(c.isLetter()) // true
|
||||
```
|
||||
`Char` **не является числом**: `val n: Int = 'A'` не скомпилируется, нужен `'A'.code`.
|
||||
Подробнее: [Char](../Работа%20с%20данными/Char.md)
|
||||
|
||||
## Преобразования
|
||||
Неявных расширяющих преобразований нет вообще - только явные вызовы:
|
||||
```kotlin
|
||||
val i = 42
|
||||
val l: Long = i.toLong() // обязательно явно
|
||||
val b = i.toByte()
|
||||
val d = i.toDouble()
|
||||
```
|
||||
Доступны `toByte()`, `toShort()`, `toInt()`, `toLong()`, `toFloat()`, `toDouble()`, `toChar()`.
|
||||
|
||||
## Строки
|
||||
`String` - неизменяемый тип, элементы доступны по индексу:
|
||||
```kotlin
|
||||
val s = "Kotlin"
|
||||
println(s[0]) // K
|
||||
println(s.length) // 6
|
||||
```
|
||||
Подробнее: [Строки](../Работа%20с%20данными/Строки.md)
|
||||
|
||||
## Nullable-типы
|
||||
Любой тип имеет nullable-вариант с `?`:
|
||||
```kotlin
|
||||
// val a: Int = null // ошибка компиляции
|
||||
val b: Int? = null // ok
|
||||
```
|
||||
Это ядро языка, ему посвящён отдельный раздел: [Null-безопасность](../Null-безопасность/Null-безопасность.md)
|
||||
|
||||
> [!info] Отличия от Java
|
||||
> | Java | Kotlin |
|
||||
> |---|---|
|
||||
> | `int` и `Integer` - разные типы | только `Int`, компилятор сам выбирает представление |
|
||||
> | автоупаковка неявная | упаковка скрыта, в коде не видна |
|
||||
> | `long x = intValue;` работает | нужен `intValue.toLong()` |
|
||||
> | `char` - числовой тип | `Char` - отдельный тип, не число |
|
||||
> | нет беззнаковых типов | `UInt`, `ULong`, … |
|
||||
> | `017` - восьмеричный литерал | восьмеричных литералов нет |
|
||||
>
|
||||
> Сравнить: [Типы данных в Java](../../../Программирование%20на%20Java/Синтаксис%20и%20типы/Базовый%20синтаксис/Типы%20данных.md)
|
||||
|
||||
> [!warning] Подводные камни
|
||||
> **Переполнение не проверяется**, как и в Java:
|
||||
> ```kotlin
|
||||
> println(Int.MAX_VALUE + 1) // -2147483648
|
||||
> ```
|
||||
>
|
||||
> **Равенство упакованных значений.** Если тип nullable, значение упаковано, и `===` сравнивает ссылки:
|
||||
> ```kotlin
|
||||
> val a: Int = 127
|
||||
> val b: Int? = a
|
||||
> val c: Int? = a
|
||||
> println(b == c) // true — сравнение значений
|
||||
> println(b === c) // true — кеш Integer для -128..127
|
||||
>
|
||||
> val x: Int? = 1000
|
||||
> val y: Int? = 1000
|
||||
> println(x == y) // true
|
||||
> println(x === y) // false — за пределами кеша это разные объекты
|
||||
> ```
|
||||
> Вывод: для чисел всегда `==`, никогда `===`.
|
||||
>
|
||||
> **`Float` и `Double` не точны**, это стандарт IEEE 754:
|
||||
> ```kotlin
|
||||
> println(0.1 + 0.2) // 0.30000000000000004
|
||||
> ```
|
||||
> Для денег - `java.math.BigDecimal`.
|
||||
|
||||
Дополнительно: [Числа и переполнение](../Работа%20с%20данными/Числа%20и%20переполнение.md)
|
||||
Далее: [Переменные](Переменные.md)
|
||||
Reference in New Issue
Block a user