6.4 KiB
title, description, tags
| title | description | tags | ||
|---|---|---|---|---|
| Типы данных | Система типов Kotlin, числа, boolean, Char и отсутствие примитивов на уровне языка |
|
В Kotlin: статическая типизация, сильная, с выводом типов.
Главное отличие от Java: на уровне языка примитивов нет. Всё - объект, у всего есть методы.
val x: Int = 42
println(x.toString()) // у числа есть методы
println(42.coerceIn(0, 10)) // 10
Но в байт-коде Int компилируется в int, если это возможно - производительность не теряется. Подробнее в Kotlin в байт-коде.
Иерархия типов
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
Числовые типы
| Тип | Размер, бит | Диапазон |
|---|---|---|
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.
Литералы
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 нет совсем.
val u: UInt = 4_000_000_000u // суффикс u
println(UInt.MAX_VALUE) // 4294967295
Нужны редко: работа с бинарными форматами, протоколами, хешами.
Boolean
val yes: Boolean = true
val both = yes && other() // ленивые операторы, как в Java
val eager = yes and other() // не ленивый: other() вызовется всегда
Char
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
Преобразования
Неявных расширяющих преобразований нет вообще - только явные вызовы:
val i = 42
val l: Long = i.toLong() // обязательно явно
val b = i.toByte()
val d = i.toDouble()
Доступны toByte(), toShort(), toInt(), toLong(), toFloat(), toDouble(), toChar().
Строки
String - неизменяемый тип, элементы доступны по индексу:
val s = "Kotlin"
println(s[0]) // K
println(s.length) // 6
Подробнее: Строки
Nullable-типы
Любой тип имеет nullable-вариант с ?:
// val a: Int = null // ошибка компиляции
val b: Int? = null // ok
Это ядро языка, ему посвящён отдельный раздел: Null-безопасность
[!info] Отличия от Java
Java Kotlin intиInteger- разные типытолько Int, компилятор сам выбирает представлениеавтоупаковка неявная упаковка скрыта, в коде не видна long x = intValue;работаетнужен intValue.toLong()char- числовой типChar- отдельный тип, не числонет беззнаковых типов UInt,ULong, …017- восьмеричный литералвосьмеричных литералов нет Сравнить: Типы данных в Java
[!warning] Подводные камни Переполнение не проверяется, как и в Java:
println(Int.MAX_VALUE + 1) // -2147483648Равенство упакованных значений. Если тип nullable, значение упаковано, и
===сравнивает ссылки: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:println(0.1 + 0.2) // 0.30000000000000004Для денег -
java.math.BigDecimal.
Дополнительно: Числа и переполнение Далее: Переменные