Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

String is Java’s standard type for text. It is a final, immutable class: once a string is created, its value cannot change. This guide shows how to create, inspect, compare, search, transform, combine, and format strings—and explains the distinctions that most often cause bugs, including == versus equals(), UTF-16 indexing, and trim() versus strip().

What is a String in Java?

java.lang.String is the class Java uses to represent sequences of text. It is final and immutable: methods that appear to change a string return another String; they do not modify the original. Immutability lets strings be shared safely. Oracle’s String API documentation describes strings as constant values that cannot be changed after creation.

String text is represented in UTF-16. A Java char is one 16-bit code unit, not necessarily one complete Unicode character. Characters outside the Basic Multilingual Plane use a pair of char values called a surrogate pair. Consequently, length() counts UTF-16 code units, not user-perceived characters.

Start with a literal and common operations

import java.util.Locale;

String language = "Java";
String greeting = "Hello, " + language + "!";
boolean sameText = greeting.equals("Hello, Java!");
int chars = greeting.length();
String upper = greeting.toUpperCase(Locale.ROOT);
String part = greeting.substring(0, 5);

sameText is true, chars is 12, and part is "Hello". The upper conversion returns a new string; greeting remains unchanged. Use Locale.ROOT for locale-neutral case conversion, such as normalizing text for a technical comparison. For text intended for a particular language or user, choose the appropriate locale instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How do you create strings?

A string literal is the simplest choice, and every literal is a String instance. Other constructors and factory methods are useful when text comes from a character array, code points, bytes, or another value.

  • Literal: String name = "Ada";
  • Character array: String text = new String(new char[] {'h', 'i'});
  • Code points: String text = new String(new int[] {0x1F600}, 0, 1);
  • Bytes: String text = new String(bytes, StandardCharsets.UTF_8); Specify a charset rather than relying on the machine’s default.
  • Value conversion: String.valueOf(value) converts supported values to text.

Creating a copy with new String("Java") is normally unnecessary. It can be useful to demonstrate object identity, but ordinary code should generally use the literal or existing string directly.

Why are strings immutable?

Immutability means a string’s contents remain stable after construction. Code can pass the same string to multiple consumers without one changing the text seen by another. It also makes string literals and other shared string values safe to reuse. A transformation such as replace(), strip(), or toUpperCase() produces a result string; keep the result if you need it.

String original = "  Java  ";
String cleaned = original.strip();
// original is still "  Java  "; cleaned is "Java"

How do == and equals() differ for strings?

equals() checks whether two strings contain the same text. The == operator checks whether two references point to the same object. Use equals() when the question is whether two strings have equal content.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
String a = "ja" + "va";       // compile-time constant expression
String b = new String("java"); // distinct object
System.out.println(a.equals(b)); // true: same content
System.out.println(a == b);      // false: different references

Java may share references for literals and compile-time constant expressions, so == can appear to work for some string comparisons. Run-time concatenation has different identity behavior; do not rely on interning or construction details for content checks. The Java Language Specification, Java SE 26 defines literal and constant-expression behavior, as well as the rules for run-time string creation.

How do you inspect and count string text?

Use the inspection method that matches the question being asked:

  • length() returns the number of UTF-16 code units. isEmpty() checks whether the length is zero; isBlank() checks whether the string is empty or consists only of whitespace.
  • charAt(index) returns the UTF-16 code unit at an index. It may return only half of a supplementary character.
  • codePointAt(index) reads a Unicode code point, and codePoints() provides a stream of code points. chars() instead streams UTF-16 code units.

For example, a supplementary character can contribute two to length() while being one Unicode code point. Even counting code points does not necessarily count what a person perceives as a single character: some visible symbols are formed from multiple code points. If your application needs user-perceived character counts or cursor movement, use a Unicode-aware approach designed for grapheme clusters rather than treating a Java index as a character count.

Which string comparison method should you use?

Method What it answers Use it for
equals() Are the contents exactly equal? Exact text matching.
equalsIgnoreCase() Are the contents equal when case differences are ignored? Simple case-insensitive checks, not language-specific sorting.
compareTo() How do the strings compare lexicographically? Ordering based on Java’s string comparison rules.
Collator How should text sort under language-sensitive rules? Human-language sorting where locale-specific collation matters.

Do not substitute compareTo() for a locale-aware sort when users expect dictionary-like ordering. Use java.text.Collator with the relevant locale for linguistic comparisons. Likewise, equalsIgnoreCase() is not a general substitute for language-specific text matching.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How do you search and extract part of a string?

Use the smallest method that expresses the search:

  • contains(text) tests whether a sequence occurs anywhere.
  • startsWith(prefix) and endsWith(suffix) test the ends.
  • indexOf(text) finds the first occurrence; lastIndexOf(text) finds the last. Both return -1 when there is no match.
  • substring(begin, end) extracts from the start index up to, but not including, the end index. subSequence(begin, end) provides the corresponding CharSequence view of that range.
String path = "docs/guide.html";
int slash = path.indexOf('/');
String firstPart = path.substring(0, slash); // "docs"

String indices are UTF-16 code-unit offsets. When searching or slicing text containing supplementary characters, make sure the index boundaries do not split a surrogate pair.

How do you replace, split, and remove whitespace?

Replacement and splitting

replace() performs literal character or sequence replacement. replaceAll() and replaceFirst() interpret the search pattern as a regular expression, so regex metacharacters may need escaping.

String sentence = "one.two";
String literal = sentence.replace(".", "-");       // "one-two"
String regex = sentence.replaceAll("\.", "-");  // "one-two"

split(regex) also takes a regular expression, not a literal delimiter. Its default behavior drops trailing empty fields. Pass a negative limit to preserve them when that distinction matters: "a,b,".split(",", -1) returns three elements, including the final empty one.

trim() versus strip()

trim() removes leading and trailing characters whose code points are at or below U+0020. strip(), available since Java 11, uses the Unicode whitespace definition represented by Character.isWhitespace(int). Choose based on the input and whitespace rules your application needs; neither method changes the original string.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Case conversion

For consistent, locale-neutral conversion, pass Locale.ROOT to toLowerCase() or toUpperCase(). Case conversion without an explicit locale depends on the default locale, which can produce different results in different environments.

How do Java text blocks work?

Text blocks provide a readable way to write multi-line string literals. The Java Language Specification defines a text block as characters enclosed by opening and closing delimiters. For example:

String json = """
    {
      "name": "Ada"
    }
    """;

The resulting value is not simply a byte-for-byte copy of the source layout. Java normalizes line endings, removes incidental indentation according to the text block’s content and closing delimiter, then interprets escape sequences. Review the Java SE 26 specification for the language rules; the Java SE 21 specification also documents text-block processing.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When should you use StringBuilder or StringBuffer?

Use ordinary + concatenation when it makes a small expression clear. For repeated construction—especially when appending inside a loop—a mutable buffer makes the intent explicit and avoids expressing the task as a sequence of immutable intermediate values. Compiler and JDK optimizations can affect how concatenation is implemented, so do not assume a performance result without measuring the actual workload.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Type Mutability Thread-safety expectation Typical fit
String Immutable Shareable as an immutable value Text values, method inputs and results, and short clear concatenations.
StringBuilder Mutable Not synchronized Repeated construction in a single-threaded context or when access is otherwise confined.
StringBuffer Mutable Its operations are synchronized Legacy or shared-buffer code that specifically needs synchronized operations; synchronization alone does not make a multi-step workflow atomic.
StringBuilder builder = new StringBuilder();
for (String item : items) {
    if (builder.length() > 0) {
        builder.append(", ");
    }
    builder.append(item);
}
String joined = builder.toString();

For straightforward joining, consider String.join(delimiter, values) or a stream collector instead of managing a buffer yourself. All these approaches ultimately interoperate with APIs that accept or return String.

How do you format a string?

String.format() and formatted() apply format specifiers, while Formatter offers a formatter object for cases needing more control. Select a locale when formatting numbers or other locale-sensitive values so decimal separators and related conventions are intentional.

String report = String.format(Locale.US, "Total: %.2f", total);
String message = "User: %s".formatted(userName);

A format string that is incompatible with its arguments or otherwise invalid can throw an IllegalFormatException at run time. Check specifiers and argument types when constructing or changing format strings. See the Java SE 27 String API for format() and formatted() details.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.