String.length: примеры (JAVA)
String.length: intОбщее описание метода
Метод length() класса java.lang.String возвращает количество char-единиц в строке. Сигнатура метода:
public int length()
Параметры: отсутствуют. Возвращаемое значение: int - ненулевое целое неотрицательное значение, равное числу 16-битных символов (char) в строке. Для пустой строки возвращается 0.
Важно понимать разницу между количеством char-единиц и количеством получаемых визуальных символов (grapheme clusters) или Unicode code points. В Java строки хранятся в UTF-16-представлении: символы из вне BMP (Basic Multilingual Plane), например некоторые эмодзи, кодируются парой суррогатных char-значений и учитываются в length() как 2. Для получения числа Unicode code points используется codePointCount(int beginIndex, int endIndex).
Особенности:
- Метод принимает ноль аргументов.
- Возвращает число char-единиц (UTF-16 code units), а не байтов и не обязательно визуальных символов.
- Вызов на
nullприводит к NullPointerException. - Поведение API не изменялось семантически в последних версиях Java: метод по-прежнему возвращает
intи работает за O(1).
Короткие примеры использования
Несколько наглядных примеров кода и их результатов.
Пример 1. Обычная строка
String s = "Hello";
System.out.println(s.length());
5
Пример 2. Пустая строка
String empty = "";
System.out.println(empty.length());
0
Пример 3. Unicode символы из вне BMP (эмодзи)
String emoji = "????"; // U+1F60A
System.out.println(emoji.length());
System.out.println(emoji.codePointCount(0, emoji.length()));
2 1
Пример 4. Вызов на null (ошибка)
String n = null;
// следующая строка приведет к исключению
System.out.println(n.length());
Exception in thread "main" java.lang.NullPointerException at ...
Аналоги и близкие методы в Java
Перечисление методов и полей, связанных по смыслу с String.length():
CharSequence.length()- интерфейс: если код работает с абстракциейCharSequence, предпочтение в пользу этого метода, так как он универсален дляString,StringBuilder,StringBufferи т.д.StringBuilder.length()иStringBuffer.length()- возвращают количество char-единиц у изменяемых строковых буферов; используются при модификации строки.String.codePointCount(int, int)- возвращает количество Unicode code points на отрезке; применяется, когда важны кодовые точки, а не UTF-16 единицы.String.getBytes(Charset).length- даёт размер в байтах для конкретной кодировки; полезен при работе с сетевым/файловым вводом-выводом.
Когда выбирать:
- Для простого измерения числа char-единиц подходит
length(). - Для совместимости с разными реализациями символных последовательностей использовать
CharSequence.length(). - Для подсчёта реальных Unicode-символов (code points) использовать
codePointCount. - Для размера в байтах использовать
getBytes(...).length, но учитывать кодировку.
Аналоги в других языках
Краткие заметки о поведении аналогичных функций в популярных языках и примеры.
JavaScript
let s = '????';
console.log(s.length);
2
Как и в Java, .length возвращает число UTF-16 code units. Для числа Unicode code points можно использовать [...s].length или итерацию по строке.
Python (3)
s = '????'
print(len(s))
1
В Python 3 len возвращает число Unicode code points (в современных сборках). Для байтов нужен len(s.encode('utf-8')).
PHP
$s = '????';
echo strlen($s) . PHP_EOL;
echo mb_strlen($s, 'UTF-8') . PHP_EOL;
4 1
strlen возвращает число байтов в строке (в UTF-8 эмодзи 4 байта). Для символов использовать mb_strlen.
C#
string s = "????";
Console.WriteLine(s.Length);
2
Сходно с Java: Length возвращает число char-единиц (UTF-16).
Go
s := "????"
fmt.Println(len(s))
fmt.Println(utf8.RuneCountInString(s))
4 1
В Go len возвращает число байтов. Для числа Unicode-символов использовать utf8.RuneCountInString.
Kotlin
val s = "????"
println(s.length)
2
Kotlin использует UTF-16-представление и поведение length совпадает с Java.
Lua
s = '????'
print(#s)
4
В Lua строки - байтовые последовательности. Для Unicode-символов требуется дополнительная обработка.
SQL (пример MySQL)
SELECT LENGTH('????'), CHAR_LENGTH('????');
4 1
LENGTH возвращает число байтов, CHAR_LENGTH - количество символов (в терминах базы) в данном наборе символов.
Типичные ошибки и их примеры
- NullPointerException при вызове
length()на ссылкеnull. - Путаница между байтами, кодовыми единицами и визуальными символами - ожидание одного результата, а получение другого.
- Использование
length()для подсчёта графем (складывающиеся символы с диакритикой), что даёт неверное число «видимых символов».
Пример 1: NullPointerException
String s = null;
System.out.println(s.length());
Exception in thread "main" java.lang.NullPointerException at ...
Пример 2: Неправильное ожидание для эмодзи
String s = "????????"; // флаг, состоит из двух региональных индикаторов
System.out.println(s.length());
System.out.println(s.codePointCount(0, s.length()));
4 2
Ожидание: 1 визуальный символ (флаг). Результат length() = 4, потому что флаг состоит из двух code points, каждый из которых кодируется двумя char.
Пример 3: Ошибка при сравнении с байтовой длиной
String s = "Привет"; // в UTF-8 больше байтов, чем char
System.out.println(s.length());
System.out.println(s.getBytes(StandardCharsets.UTF_8).length);
6 12
Нельзя использовать length() для расчёта места на диске без учёта кодировки.
Изменения в реализации и поведение в новых версиях
API метода length() не претерпевал семантических изменений: он по-прежнему возвращает int и число UTF-16 code units. Существенные изменения внутри платформы:
- В Java 9 произошли внутренние изменения реализации
String(compact strings): переход на хранение в видеbyte[]с полем кодера. Это не изменило поведениеlength(), метод всё так же возвращает количество символных единиц. - Появление дополнительных утилит для работы с Unicode (например, методы для работы с code points и методами для обработки пробелов), но
length()осталось прежним.
Вывод: коду, использующему length(), изменений не требуется; при необходимости учёта реальных графем или байтов следует применять другие API.
Расширенные и нестандартные примеры использования
1) Подсчёт Unicode code points во всей строке
String s = "A????𝄞"; // A, emoji, музыкальная нота (surrogate pair)
int codePoints = s.codePointCount(0, s.length());
System.out.println("length (char units): " + s.length());
System.out.println("code points: " + codePoints);
length (char units): 4 code points: 3
Пояснение: метод length() возвращает количество char-единиц, а codePointCount - количество Unicode code points.
2) Получение подстроки по индексам в терминах code points
String s = "A????B";
int startCp = 1; // второй кодовый символ (emoji)
int endCp = 3; // до конца
int startIndex = s.offsetByCodePoints(0, startCp);
int endIndex = s.offsetByCodePoints(0, endCp);
String sub = s.substring(startIndex, endIndex);
System.out.println(sub);
System.out.println(sub.length());
????B 3
Пояснение: offsetByCodePoints переводит позиции кодовых точек в индексы char, что позволяет корректно извлечь подстроку с учетом суррогатов.
3) Подсчёт визуальных символов (grapheme clusters) с использованием BreakIterator
String s = "Z͑́é\uD83D\uDE0A"; // Z + комбинирующие, e + accent, smile
BreakIterator it = BreakIterator.getCharacterInstance(Locale.getDefault());
it.setText(s);
int count = 0;
int start = it.first();
while (start != BreakIterator.DONE) {
int end = it.next();
if (end == BreakIterator.DONE) break;
count++;
}
System.out.println(count);
3
Пояснение: BreakIterator считает графемные кластеры, приближая понятие визуальных символов.
4) Измерение байтового размера в UTF-8 для определения ограничения по трафику
String s = "Привет ????";
byte[] utf8 = s.getBytes(StandardCharsets.UTF_8);
System.out.println("chars: " + s.length());
System.out.println("bytes UTF-8: " + utf8.length);
chars: 9 bytes UTF-8: 14
Пояснение: количество char-единиц не равно количеству байтов в UTF-8.
5) Быстродействие: вызов length() за O(1)
String s = "a".repeat(10000000);
long t0 = System.nanoTime();
int len = s.length();
long t1 = System.nanoTime();
System.out.println(len);
System.out.println((t1 - t0) + " ns");
10000000 [небольшое число наносекунд, зависит от машины]
Пояснение: length() возвращает заранее известное значение и работает за константное время.
6) Сравнение поведения для разных реализаций CharSequence
CharSequence cs1 = "Hello"; // String
CharSequence cs2 = new StringBuilder("Hello");
System.out.println(cs1.length());
System.out.println(cs2.length());
5 5
Пояснение: использование интерфейса CharSequence позволяет писать код, не зависящий от конкретной реализации.
7) Обработка суррогатных пар при обходе строки
String s = "\uD83D\uDE00\uD83D\uDE01"; // два emoji
int i = 0;
while (i < s.length()) {
int cp = s.codePointAt(i);
System.out.printf("code point: U+%X\n", cp);
i += Character.charCount(cp);
}
code point: U+1F600 code point: U+1F601
Пояснение: при обходе по char-единицам необходимо использовать методы для работы с кодовыми точками, чтобы не разрезать суррогатные пары.