--- title: Char description: Char как отдельный тип, код символа, проверки категорий и работа с цифрами tags: - kotlin - stdlib --- `Char` - один символ в одинарных кавычках. Хранит кодовую единицу UTF-16 (16 бит). ```kotlin val c: Char = 'A' val tab = '\t' val quote = '\'' val unicode = '\u00A9' // © ``` Ключевое отличие от Java: **`Char` не является числом**. Арифметику с ним делать можно, но неявного превращения в `Int` нет. ```kotlin 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` | ## Проверки категорий ```kotlin 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`. ## Регистр ```kotlin println('a'.uppercaseChar()) // A — возвращает Char println('A'.lowercaseChar()) // a println('a'.uppercase()) // "A" — возвращает String println('ß'.uppercase()) // "SS" — два символа, поэтому String ``` Есть две версии: `uppercaseChar()` даёт `Char`, `uppercase()` - `String`. Вторая нужна, потому что в Unicode регистр не всегда меняется один-к-одному. ## Цифры ```kotlin println('7'.digitToInt()) // 7 — число, а не код символа println('f'.digitToInt(16)) // 15 println('x'.digitToIntOrNull()) // null — безопасная версия println(7.digitToChar()) // '7' ``` Это главный способ разобрать цифру. Старый трюк из Java (`c - '0'`) тоже работает, но `digitToInt()` понятнее и проверяет корректность: ```kotlin println('7' - '0') // 7 — работает // println('x'.digitToInt()) // IllegalArgumentException ``` ## Диапазоны и сравнение ```kotlin 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 ```kotlin 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` к строке можно сложением - слева обязательно строка: ```kotlin 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](../../../Программирование%20на%20Java/Синтаксис%20и%20типы/Работа%20с%20данными%20и%20типами/Character.md) > [!warning] Подводные камни > **`Char` не вмещает символы за пределами BMP.** Эмодзи и редкие иероглифы кодируются двумя `Char` (surrogate pair): > ```kotlin > val emoji = "😀" > println(emoji.length) // 2 > println(emoji[0].isLetter()) // false — половина пары бессмысленна > println(emoji.codePointAt(0)) // 128512 — полный код символа > ``` > Для посимвольной обработки текста с эмодзи нужны кодовые точки, а не `Char`. > > **`digitToInt()` бросает исключение, а не возвращает -1:** > ```kotlin > println('x'.digitToIntOrNull()) // null — безопасно > // println('x'.digitToInt()) // IllegalArgumentException > ``` > > **`'1'.code` - это 49, а не 1.** Путать код символа с его числовым значением - классическая ошибка: > ```kotlin > println('1'.code) // 49 > println('1'.digitToInt()) // 1 > ``` > > **`Char` в `when` требует `else`** - перечислить все 65 536 значений компилятор не может. > > **`uppercase()` возвращает `String`, и это не придирка.** `'ß'.uppercase()` даёт `"SS"` - два символа. Если нужен именно `Char`, используйте `uppercaseChar()`, но помните, что для `'ß'` он вернёт сам `'ß'`. Далее: [Числа и переполнение](Числа%20и%20переполнение.md)