String Length
length() returns the number of characters in a string, or more precisely, the number of UTF-16 code units (char values) it contains. For everyday text in most languages, that is the same as the number of characters you see. For emoji, some symbols, and text that uses combining marks, the visible character count can differ. This lesson covers length(), the indexes it defines, how to use it safely, and how to measure text correctly when the difference matters.
Using length()
String course = "Java Basics";
System.out.println(course.length()); // 11 (the space counts)
System.out.println("".length()); // 0
System.out.println(" ".length()); // 2 (whitespace counts)
length() is a method on String, written with parentheses. This differs from arrays (array.length, a field) and collections (list.size()).
| Type | Count expression |
|---|---|
String, StringBuilder | s.length() |
| Array | arr.length |
List, Set, Map | c.size() |
Calling length() on null throws NullPointerException, so check for null first when a value may be missing.
Indexes and length()
Characters are numbered from 0 to length() - 1:
J a v a B a s i c s
0 1 2 3 4 5 6 7 8 9 10 length() = 11
String s = "Java Basics";
char first = s.charAt(0); // 'J'
char last = s.charAt(s.length() - 1); // 's'
s.charAt(s.length()); // StringIndexOutOfBoundsException
Index-based methods use length() as their natural boundary:
s.substring(5); // "Basics": from index 5 to the end
s.substring(0, 4); // "Java": end index is exclusive
s.substring(s.length() - 3); // "ics": the last 3 characters
substring(begin, end) returns end - begin characters. end may equal length() but not exceed it.
Common Uses of length()
Validating input
static String validatePassword(String pw) {
if (pw == null || pw.length() < 10) {
return "Password must be at least 10 characters";
}
if (pw.length() > 128) {
return "Password is too long";
}
return "OK";
}
Looping over characters
String text = "Hello, World";
int upper = 0;
for (int i = 0; i < text.length(); i++) {
if (Character.isUpperCase(text.charAt(i))) upper++;
}
System.out.println(upper); // 2
Padding and alignment
String id = "42";
String padded = "0".repeat(Math.max(0, 6 - id.length())) + id; // "000042"
String.format("%06d", 42) produces the same result for numbers.
Empty and blank checks
isEmpty() is equivalent to length() == 0. Whitespace still counts toward the length, so use isBlank() to treat whitespace-only strings as empty, or measure after stripping:
String input = " Ada ";
System.out.println(input.length()); // 9
System.out.println(input.strip().length()); // 3
When length() Is Not the Number of Visible Characters
Java strings are stored as UTF-16. Characters in Unicode's Basic Multilingual Plane (Latin, Greek, Cyrillic, Arabic, Devanagari, Tamil, Chinese, Japanese, and most other scripts) use one char each. Characters outside it, including most emoji and some rare scripts and symbols, use two char values, called a surrogate pair.
There are three different things you might want to count:
| Measure | Method | Counts |
|---|---|---|
| UTF-16 code units | s.length() | char values; what indexes are based on |
| Unicode code points | s.codePointCount(0, s.length()) | Individual Unicode characters |
| Grapheme clusters | BreakIterator.getCharacterInstance() | What a reader perceives as one character |
String launch = "Launch 🚀";
System.out.println(launch.length()); // 9: the rocket uses 2 chars
System.out.println(launch.codePointCount(0, launch.length())); // 8
Grapheme clusters go further. A single visible symbol can consist of several code points: a base letter plus combining marks (common in Tamil and other Indic scripts), an emoji plus a skin-tone modifier, or a family emoji joined with invisible joiner characters. The practical example below compares all three measures.
Breaking surrogate pairs
Index-based operations work on char positions, so they can cut a surrogate pair in half, producing an invalid character that displays as ? or a replacement box:
String post = "Shipping the new Java course today 🚀🚀🚀";
String cut = post.substring(0, 36); // ends with half of the first rocket
To cut safely, convert a number of code points into a char offset with offsetByCodePoints:
int end = post.offsetByCodePoints(0, 35); // char index after the first 35 code points
String safe = post.substring(0, end);
For most business text (names, addresses, product descriptions in a single script), length() is entirely adequate. Use code points or grapheme clusters when limits are shown to users ("280 characters remaining"), when truncating user-generated content, or when reversing or splitting text that may contain emoji.
Length in Bytes
The number of characters is different again from the number of bytes a string occupies when encoded for a file, database column, or network message:
String cafe = "Café";
System.out.println(cafe.length()); // 4
System.out.println(cafe.getBytes(StandardCharsets.UTF_8).length); // 5: é takes 2 bytes
System.out.println("வணக்கம்".getBytes(StandardCharsets.UTF_8).length); // 21
In UTF-8, ASCII characters take 1 byte, most European accented letters 2, most Indic and CJK characters 3, and emoji 4. When a database column or protocol field has a byte limit, measure the encoded bytes, not length().
Practical Example: Measuring Text for a Post Composer
A social media composer needs to show a character count and truncate long posts without breaking emoji.
import java.nio.charset.StandardCharsets;
import java.text.BreakIterator;
public class Len {
static int graphemes(String s) {
BreakIterator it = BreakIterator.getCharacterInstance();
it.setText(s);
int count = 0;
while (it.next() != BreakIterator.DONE) count++;
return count;
}
static String truncate(String s, int maxCodePoints) {
if (s.codePointCount(0, s.length()) <= maxCodePoints) return s;
int end = s.offsetByCodePoints(0, maxCodePoints - 1);
return s.substring(0, end) + "…";
}
public static void main(String[] args) {
String[] samples = {"Java", "Café", "வணக்கம்", "Launch 🚀", "👍🏽"};
for (String s : samples) {
System.out.printf("%-12s chars=%d codePoints=%d utf8Bytes=%d graphemes=%d%n", "\"" + s + "\"", s.length(),
s.codePointCount(0, s.length()),
s.getBytes(StandardCharsets.UTF_8).length, graphemes(s));
}
String tweet = "Shipping the new Java course today 🚀🚀🚀";
System.out.println(truncate(tweet, 36));
System.out.println(tweet.length() + " " + tweet.indexOf("🚀"));
String cut = tweet.substring(0, 36);
System.out.println(Character.isHighSurrogate(cut.charAt(cut.length() - 1)));
}
}
Output (on a terminal configured for UTF-8, which may require running with -Dstdout.encoding=UTF-8 on some systems):
"Java" chars=4 codePoints=4 utf8Bytes=4 graphemes=4
"Café" chars=4 codePoints=4 utf8Bytes=5 graphemes=4
"வணக்கம்" chars=7 codePoints=7 utf8Bytes=21 graphemes=5
"Launch 🚀" chars=9 codePoints=8 utf8Bytes=11 graphemes=8
"👍🏽" chars=4 codePoints=2 utf8Bytes=8 graphemes=1
Shipping the new Java course today …
41 35
true
The table shows how the measures diverge:
- ASCII text (
Java) has the same value for all four. Caféhas 4 characters but 5 UTF-8 bytes.- The Tamil word has 7
charvalues and 7 code points but 5 grapheme clusters, because vowel signs and the virama combine with the preceding consonant into a single visible unit. - The rocket emoji adds 2 to
length()but 1 to the code point count. - The thumbs-up with a skin tone is 4
charvalues, 2 code points, and a single visible symbol.
truncate counts and cuts in code points, so the post is shortened cleanly before the first rocket and an ellipsis is added. The last two lines show why this matters: the first rocket starts at char index 35, so a naive substring(0, 36) ends with a lone high surrogate, which would display as a broken character. (The %-12s padding also counts char values, which is why the columns do not line up perfectly for the emoji rows.)