Перейти к содержимому
Теория · Строки · урок 9 из 11

Символы char

Метод charAt возвращает не строку, а один символ — значение типа char. В этом уроке разберём, что лежит внутри такого значения и почему символы иногда складываются как числа.

Вернёмся к карточке. В каждой её клетке видна буква, но компьютер хранит не буквы, а числа. У каждого символа есть номер в общей таблице символов Юникод: у a это 97, у b — 98, у A — 65. Клетка карточки на самом деле хранит этот номер, а println при печати превращает его обратно в букву:

JAVA
public class Main {
    public static void main(String[] args) {
        char c = 'a';
        System.out.println(c);              // a
        System.out.println((int) c);        // 97
        System.out.println(c + 1);          // 98
        System.out.println((char) (c + 1)); // b
    }
}

Давайте разберём программу по строкам:

  1. char c = 'a'; кладёт в c символ a, а внутри — его номер 97.
  2. println(c) печатает символ: println видит, что перед ним char.
  3. (int) c приводит символ к int и показывает номер — 97.
  4. c + 1 — уже арифметика: результат имеет тип int, и печатается 98.
  5. (char) (c + 1) приводит число 98 обратно к char, и печатается b.

char — это число

Код символа — его номер в таблице Юникод. Значение char — 16-битное число без знака, от 0 до 65535, и хранит оно именно код. Поэтому с char работает арифметика:

  • в выражении с int или с другим char символ превращается в int, и результат тоже int;
  • чтобы получить символ обратно, нужно приведение (char);
  • коды латинских букв и цифр идут подряд: 'a' — 97, 'b' — 98, 'A' — 65, '0' — 48.

char и String в одном выражении

Вспомните правило склейки: если с одной стороны от + стоит строка, + склеивает. Если строки нет, + складывает числа, а char — это число:

JAVA
String name = "Bob";
char first = name.charAt(0);
System.out.println(first == 'B');   // true
System.out.println(first + 1);      // 67
System.out.println("" + first + 1); // B1
  1. first == 'B' даёт true. char — примитивный тип, поэтому == сравнивает сами значения, а не ссылки, как у строк.
  2. first + 1 складывает код B, 66, с единицей и печатает 67.
  3. В "" + first + 1 слева пустая строка, поэтому оба + склеивают, и печатается B1.

На собеседовании любят спросить, что напечатает сумма двух символов в println. Ответ даёт то же правило: строки нет — значит, складываются коды.

Здесь картинка с карточкой неточна. Кажется, что любой символ занимает ровно одну клетку. Но 16 бит хватает не на всё: многие эмодзи занимают в строке по две клетки-char, и "😀".length() даёт 2.

Проверки символов

Для проверок символов есть класс Character с готовыми методами:

  • Character.isDigit(c) — цифра ли это;
  • Character.isLetter(c) — буква ли это;
  • Character.toUpperCase(c) — та же буква, но заглавная.

Это static-методы: их вызывают через имя класса, и import для них не нужен. Вот подсчёт цифр в строке:

JAVA
String code = "A7-42b";
int digits = 0;
for (int i = 0; i < code.length(); i++) {
    if (Character.isDigit(code.charAt(i))) {
        digits++;
    }
}
System.out.println(digits); // 3

Цикл проходит по индексам от 0 до length() - 1. charAt(i) достаёт очередной символ, а Character.isDigit проверяет, цифра ли он. Цифр в строке три: 7, 4 и 2.

Частая ошибка

Инициалы собрали из двух charAt через +:

JAVA
String first = "Anna";
String last = "Lee";
System.out.println(first.charAt(0) + last.charAt(0)); // ✗

Хотели напечатать AL, а программа печатает 141. charAt возвращает char, строки в выражении нет, и + складывает коды 65 и 76. Поставьте слева пустую строку: "" + first.charAt(0) + last.charAt(0) печатает AL.

Главное

  • char хранит код символа — 16-битное число; (int) c показывает код, а (char) превращает код в символ.
  • Арифметика с char и int даёт int: 'a' + 1 — это 98, и два char через + складываются как числа.
  • Чтобы склеить символы, слева нужна строка: "" + c1 + c2.
  • charAt возвращает char, а класс Character проверяет символы: isDigit, isLetter.