Типы данных

Последнее обновление: 02.03.2024

В Kotlin все компоненты программы, в том числе переменные, представляют объекты, которые имеют определенный тип данных. Тип данных определяет, какой размер памяти может занимать объект данного типа и какие операции с ним можно производить. В Kotlin есть несколько базовых типов данных: числа, символы, строки, логический тип и массивы.

Целочисленные типы

  • Byte: хранит целое число от -128 до 127 и занимает 1 байт

  • Short: хранит целое число от -32 768 до 32 767 и занимает 2 байта

  • Int: хранит целое число от -2 147 483 648 (-231) до 2 147 483 647 (231 - 1) и занимает 4 байта

  • Long: хранит целое число от –9 223 372 036 854 775 808 (-263) до 9 223 372 036 854 775 807 (263-1) и занимает 8 байт

В последней версии Kotlin также добавлена поддержка для целочисленных типов без знака:

  • UByte: хранит целое число от 0 до 255 и занимает 1 байт

  • UShort: хранит целое число от 0 до 65 535 и занимает 2 байта

  • UInt: хранит целое число от 0 до 232 - 1 и занимает 4 байта

  • ULong: хранит целое число от 0 до 264-1 и занимает 8 байт

Объекты целочисленных типов хранят целые числа:

fun main(){

    val a: Byte = -10
    val b: Short = 45
    val c: Int = -250
    val d: Long = 30000
    println(a) // -10
    println(b) // 45
    println(c) // -250
    println(d) // 30000
}

По умолчанию все числовые литералы расцениваются как значения типа Int. При присвоении числовых литералов переменным других типов данных происходит неявное преобразование. Например:

fun main(){

    val a: Byte = 127  // 127 - значение типа Int преобразуетсяв тип Byte
    println(a) // 127
}

Здесь числовой литерал, который по умолчанию представляет тип Int, преобразуется к типу Byte. И в данном случае все нормально, так как 127 укладывается в диапазон значений типа Byte. Но возьмем другой пример:

fun main(){

    val a: Byte = 128  // Ошибка
    println(a) // 
}

Здесь при присвоении числа 128 переменной типа Byte мы получим ошибку, поскольку число 128 вне диапазона значений для типа Byte.

Kotlin также поддерживает литералы типа Long - такие числовые литералы имеют суффикс L:

fun main(){

    val a: Long = 22    // 22 - Int, преобразование из Int в Long
    println(a) // 22
    val b: Long = 22L   // 22L - Long, преобразование не нужно
    println(b) // 22
}

Для передачи значений объектам, которые представляют беззнаковые целочисленные типы данных, после числа указывается суффикс U:

fun main(){

    val a: UByte = 10U
    val b: UShort = 45U
    val c: UInt = 250U
    val d: ULong = 30000U
    println(a) // 10
    println(b) // 45
    println(c) // 250
    println(d) // 30000
}

Кроме чисел в десятичной системе мы можем определять числа в двоичной и шестнадцатеричной системах.

Шестнадцатеричная запись числа начинается с 0x, затем идет набор символов от 0 до F, которые представляют число:

val num: Int = 0x0A1    // 161
println(num) // 161

Двоичная запись числа предваряется символами 0b, после которых идет последовательность из нулей и единиц:

val a: Int = 0b0101    // 5
val b: Int = 0b1011     // 11
println(a)      // 5
println(b)      // 11 

Для упрощения работы с большими числами отдельные разряды чисел можно разделять с помощью прочерка:

fun main(){

    var million = 1_000_000
    var number = 1234_5678_9012_3456
    println(million)    // 1000000
    println(number)     // 1234567890123456
}

Числа с плавающей точкой

Кроме целочисленных типов в Kotlin есть два типа для чисел с плавающей точкой, которые позволяют хранить дробные числа:

  • Float: хранит число с плавающей точкой от -3.4*1038 до 3.4*1038 и занимает 4 байта

  • Double: хранит число с плавающей точкой от ±5.0*10-324 до ±1.7*10308 и занимает 8 байта.

В качестве разделителя целой и дробной части применяется точка:

val height: Double = 1.78
val pi: Float = 3.14F
println(height)      // 1.78
println(pi)      	// 3.14

Чтобы присвоить число объекту типа Float после числа указывается суффикс f или F.

Также тип Double поддерживает экспоненциальную запись:

val d: Double = 23e3
println(d)      // 23 000

val g: Double = 23e-3
println(g)      // 0.023

Логический тип Boolean

Тип Boolean может хранить одно из двух значений: true (истина) или false (ложь).

val a: Boolean = true
val b: Boolean = false

Символы

Символьные данные представлены типом Char. Он представляет отдельный символ, который заключается в одинарные кавычки.

val a: Char = 'A'
val b: Char = 'B'
val c: Char = 'T'

Также тип Char может представлять специальные последовательности, которые интерпретируются особым образом:

  • \t: табуляция

  • \n: перевод строки

  • \r: возврат каретки

  • \': одинарная кавычка

  • \": двойная кавычка

  • \\: обратный слеш

Строки

Строки представлены типом String. Строка представляет последовательность символов, заключенную в двойные кавычки, либо в тройные двойные кавычки.

fun main() {
    
    val name: String = "Eugene"

    println(name)
}

Строка может содержать специальные символы или эскейп-последовательности. Например, если необходимо вставить в текст перевод на другую строку, можно использовать эскейп-последовательность \n:

val text: String = "SALT II was a series of talks between United States \n and Soviet negotiators from 1972 to 1979"

Для большего удобства при создании многострочного текста можно использовать тройные двойные кавычки:

fun main() {

    val text: String = """
						SALT II was a series of talks between United States
						and Soviet negotiators from 1972 to 1979.
						It was a continuation of the SALT I talks.
					"""
    println(text)
}

Шаблоны строк

Шаблоны строк (string templates) представляют удобный способ вставки в строку различных значений, в частности, значений переменных. Так, с помощью знака доллара $ мы можем вводить в строку значения различных переменных:

fun main() {

    val firstName = "Tom"
    val lastName = "Smith"
    val welcome = "Hello, $firstName $lastName"
    println(welcome)	// Hello, Tom Smith
}

В данном случае вместо $firstName и $lastName будут вставляться значения этих переменных. При этом переменные необязательно должны представлять строковый тип:

val name = "Tom"
val age = 22
val userInfo = "Your name: $name  Your age: $age"

Выведение типа

Kotlin позволяет выводить тип переменной на основании данных, которыми переменная инициализируется. Поэтому при инициализации переменной тип можно опустить:

val age = 5

В данном случае компилятор увидит, что переменной присваивается значение типа Int, поэтому переменная age будет представлять тип Int.

Соответственно если мы присваиваем переменной строку, то такая переменная будет иметь тип String.

val name = "Tom"

Любые целые числа, воспринимаются как данные типа Int.

Если же мы хотим явно указать, что число представляет значение типа Long, то следует использовать суффикс L:

val sum = 45L

Если надо указать, что объект представляет беззнаковый тип, то применяется суффикс u или U:

val sum = 45U

Аналогично все числа с плавающей точкой (которые содержат точку в качестве разделителя целой и дробной части) рассматриваются как числа типа Double:

val height = 1.78

Если мы хотим указать, что данные будут представлять тип Float, то необходимо использовать суффикс f или F:

val height = 1.78F

Однако нельзя сначала объявить переменную без указания типа, а потом где-то в программе присвоить ей какое-то значение:

val age		// Ошибка, переменная не инициализирована
age = 5 

Статическая типизация

Тип данных ограничивает набор значений, которые мы можем присвоить переменной. Например, мы не можем присвоить переменной типа Double строку:

val height: Double = "1.78"

И после того, как тип переменной установлен, он не может быть изменен:

fun main() {

    var height: String = "1.78"
    height = 1.81       // !Ошибка - переменная height хранит только строки
    println(height)
}

Кроме того, мы не можем переменной одного типа напрямую присвоить значение переменной другого типа. Например:

fun main(){

    var longN: Long = 2
    var intN: Int = 4
    longN = intN   // ! Ошибка
    println(longN)
}

Здесь переменной типа Long мы пытаемся присвоить значение типа Int. В итоге мы получим ошибку. Казалось бы, значение переменной типа Int - число 4 вполне укладывается в диапазон значений типа Long. Более того саму переменную типа Long - nLong мы инициализируем значением типа Int. Тем не менее это разные типы, и мы получим ошибку.

В реальности мы можем решить эту проблему: Kotlin предоставляет нам ряд встроенных функций для преобразования данных к определенному типу:

  • toByte

  • toShort

  • toInt

  • toLong

  • toFloat

  • toDouble

  • toChar

Так, мы можем изменить пример выше, применив функцию toLong:

fun main(){

    var longN: Long = 2
    var intN: Int = 4
    longN = intN.toLong()   // Ошибки нет
    println(longN)
}

Далее мы более подробно разберем тему преобразований.

Тип Any

В Kotlin также есть тип Any, который позволяет присвоить переменной данного типа любое значение:

fun main() {

    var name: Any = "Tom"
    println(name)   // Tom
    name = 6758
    println(name)   // 6758
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850