Files
obsidian/Kotlin/Синтаксис и типы/Работа с данными/Char.md
T

6.3 KiB
Raw Blame History

title, description, tags
title description tags
Char Char как отдельный тип, код символа, проверки категорий и работа с цифрами
kotlin
stdlib

Char - один символ в одинарных кавычках. Хранит кодовую единицу UTF-16 (16 бит).

val c: Char = 'A'
val tab = '\t'
val quote = '\''
val unicode = '\u00A9'     // ©

Ключевое отличие от Java: Char не является числом. Арифметику с ним делать можно, но неявного превращения в Int нет.

val c = 'A'
// val n: Int = c        // ошибка компиляции
val n: Int = c.code      // 65 — явно
println(c + 1)           // B   — Char + Int = Char
println('z' - 'a')       // 25  — Char - Char = Int
println(c.toString())    // A
Выражение Результат Тип
'A' + 1 'B' Char
'z' - 'a' 25 Int
'A'.code 65 Int
65.toChar() 'A' Char

Проверки категорий

println('a'.isLetter())        // true
println('5'.isDigit())         // true
println('a'.isLetterOrDigit()) // true
println(' '.isWhitespace())    // true
println('a'.isLowerCase())     // true
println('A'.isUpperCase())     // true

Все эти функции учитывают Unicode: 'я'.isLetter() тоже true.

Регистр

println('a'.uppercaseChar())   // A — возвращает Char
println('A'.lowercaseChar())   // a
println('a'.uppercase())       // "A" — возвращает String
println('ß'.uppercase())       // "SS" — два символа, поэтому String

Есть две версии: uppercaseChar() даёт Char, uppercase() - String. Вторая нужна, потому что в Unicode регистр не всегда меняется один-к-одному.

Цифры

println('7'.digitToInt())          // 7 — число, а не код символа
println('f'.digitToInt(16))        // 15
println('x'.digitToIntOrNull())    // null — безопасная версия
println(7.digitToChar())           // '7'

Это главный способ разобрать цифру. Старый трюк из Java (c - '0') тоже работает, но digitToInt() понятнее и проверяет корректность:

println('7' - '0')                 // 7 — работает
// println('x'.digitToInt())       // IllegalArgumentException

Диапазоны и сравнение

println('a' in 'a'..'z')       // true
println('5' in '0'..'9')       // true
for (c in 'a'..'e') print(c)   // abcde
println('a' < 'b')             // true — по коду
println(('a'..'e').toList())   // [a, b, c, d, e]

Строки и Char

val s = "Kotlin"
println(s[0])                        // K — элемент строки это Char
println(s.first())                   // K
println(s.toCharArray().size)        // 6
println(String(charArrayOf('a','b'))) // ab — собрать строку из массива
println(s.toList())                  // [K, o, t, l, i, n]
println("abc".map { it + 1 })        // [b, c, d]
println(charArrayOf('a','b').concatToString()) // ab

Приписать Char к строке можно сложением - слева обязательно строка:

println("ab" + 'c')     // abc
// println('c' + "ab")  // ошибка: Char.plus ожидает Int
println("${'c'}ab")     // cab — через шаблон

[!info] Отличия от Java

Java Kotlin
char - числовой тип Char - отдельный тип
int n = c; работает нужен c.code
Character.isDigit(c) c.isDigit()
Character.toUpperCase(c) c.uppercaseChar()
Character.getNumericValue(c) c.digitToInt()
c - '0' для цифры c.digitToInt()
switch (c) по числам when (c) по символам

В Java char участвует в арифметике как число, из-за чего System.out.println('a' + 1) печатает 98, а не b. В Kotlin тот же код даёт b - тип сохраняется.

Все утилиты из Character стали методами Char, поэтому пишутся через точку и находятся автодополнением.

Сравнить: Character в Java

[!warning] Подводные камни Char не вмещает символы за пределами BMP. Эмодзи и редкие иероглифы кодируются двумя Char (surrogate pair):

val emoji = "😀"
println(emoji.length)              // 2
println(emoji[0].isLetter())       // false — половина пары бессмысленна
println(emoji.codePointAt(0))      // 128512 — полный код символа

Для посимвольной обработки текста с эмодзи нужны кодовые точки, а не Char.

digitToInt() бросает исключение, а не возвращает -1:

println('x'.digitToIntOrNull())    // null — безопасно
// println('x'.digitToInt())       // IllegalArgumentException

'1'.code - это 49, а не 1. Путать код символа с его числовым значением - классическая ошибка:

println('1'.code)          // 49
println('1'.digitToInt())  // 1

Char в when требует else - перечислить все 65 536 значений компилятор не может.

uppercase() возвращает String, и это не придирка. 'ß'.uppercase() даёт "SS" - два символа. Если нужен именно Char, используйте uppercaseChar(), но помните, что для 'ß' он вернёт сам 'ß'.

Далее: Числа и переполнение