Java Strings
Fast recall
Quick revision
Core answer
String is Java's standard immutable text type. It represents text as UTF-16 code units and supplies common operations for comparing, searching, slicing, and converting text. A fixed value is easy to share, intern, and use as a map key; use StringBuilder when the text must be assembled repeatedly.Interview-ready guide
Interview answer
String is Java's standard type for text. It is a final, immutable class: after a String object is created, its text does not change. The class gives every Java program the same operations for tasks such as contains(), substring(), equals(), and case conversion, instead of making each application invent its own text representation.
A call such as String upper = name.toUpperCase() produces a result and leaves name's original object unchanged. The result may be a different object, or a method may reuse the original when nothing changes. The important promise is about the value, not a promise that every method call allocates a new object.
For example, new String("Java") and the literal "Java" contain the same text, so left.equals(right) is true. They are separate objects, so left == right is false. Interning can make some equal strings share a reference, but application logic should still use equals() when it means same text.
The public model uses UTF-16. Methods such as length() and charAt() work with 16-bit code units, not always with complete user-visible characters. A supplementary character such as many emoji uses a surrogate pair and occupies two indexes. When code needs Unicode code points, use APIs such as codePointCount() or codePoints().
Immutability makes a String value safe to share and gives it stable content equality and hashing, which is useful for map keys and interning. It is less suitable for growing text one piece at a time. In that case, build with one StringBuilder, then publish the final String. The String abstraction stays stable even though OpenJDK's private storage can change between releases.
Java Strings
Direct Answer
String is Java's standard immutable text type. It represents text as UTF-16 code units and supplies common operations for comparing, searching, slicing, and converting text. A fixed value is easy to share, intern, and use as a map key; use StringBuilder when the text must be assembled repeatedly.
Deep Dive & Architecture
Text model and Unicode positions
The Java API defines String as an immutable sequence in UTF-16 form. A char is one UTF-16 code unit, so length() counts code units and charAt(index) returns one code unit. Most common letters need one unit, but a supplementary Unicode code point needs a high-surrogate and low-surrogate pair. This is why the text "A😀" has three Java indexes but two code points. Code that processes full Unicode values can use codePointAt, codePointCount, or codePoints.
Value equality and interning
Two different String objects can hold equal text. equals() compares that text, while == compares references. The language interns string literals and compile-time constant strings, and intern() returns a canonical representative. That sharing is useful, but it must not become a reason to use == for business comparisons: a String read from a file, request, or database can contain the same characters without being the same object.
Because the content is stable, a String can be shared for reading and its equality and hash value stay consistent. This makes it a natural key type. Immutability describes the String object; a field that is reassigned to different strings still needs the normal visibility rules when threads share that field.
Mutable construction and private storage
Text assembly is a different job. StringBuilder provides a mutable character sequence for repeated append calls and then produces a String with toString(). StringBuffer synchronizes its individual operations, but method-level locking does not automatically make a multi-step edit atomic.
Current OpenJDK can store many strings compactly in a byte array plus an encoding marker. Older JDKs used a different representation. That private layout is an optimization, not the meaning of String, so application code should rely on the API contract rather than a particular backing array.
Code Example
class StringOverviewDemo {
public static void main(String[] args) {
String original = "Java";
String upper = original.toUpperCase();
System.out.println(original); // Java
System.out.println(upper); // JAVA
String copy = new String("Java");
System.out.println(original.equals(copy)); // true: equal text
System.out.println(original == copy); // false: different objects
String sample = "A\uD83D\uDE00";
System.out.println(sample.length()); // 3 UTF-16 code units
System.out.println(
sample.codePointCount(0, sample.length())); // 2 code points
String result = new StringBuilder("Java")
.append(" strings")
.toString();
System.out.println(result); // Java strings
}
}
The example keeps the immutable source value, compares content separately from identity, shows the UTF-16 boundary, and uses a builder only while text is being assembled.
Check your understanding
Answer these without looking back at the article.
- Why should String content usually be compared with equals() instead of ==?
- Why can String.length() differ from the number of Unicode code points?
- When should StringBuilder replace String concatenation?
- What does String.intern() return?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.