Strings in Java

By the Syncfusion DevTutorials team · Last updated

Work with Java text: immutability, the String Pool, literals and text blocks, formatting, common String methods, comparing strings, and building text with StringBuilder and StringBuffer.

Think about a printed name badge.

The name is printed on the card. You cannot rub out one letter and write a new one. If the name is wrong, you print a fresh badge and throw the old one away.

A Java String works the same way. Once a string is created, its text never changes. Every so-called change actually creates a new string.

In simple words: a String is a piece of text, and it cannot be changed after it is created.

What You Will Learn

In this lesson, you will learn:

  1. What a String is and why it is immutable.
  2. How Java saves memory with the String Pool.
  3. How to join text and format it neatly.
  4. The most useful String methods.
  5. How to compare strings correctly.
  6. How StringBuilder and StringBuffer build text efficiently.
  7. When to use String and when to use StringBuilder.

Start With a Working Example

Press Run.

A String answers questions about its own text

public class Main {
    public static void main(String[] args) {
        String email = "  Asha.Kumar@Mail.com  ";

        String clean = email.trim().toLowerCase();

        System.out.println("Clean: " + clean);
        System.out.println("Length: " + clean.length());
        System.out.println("Gmail user? " + clean.endsWith("@gmail.com"));
        System.out.println("Name part: " + clean.substring(0, clean.indexOf("@")));
    }
}

Expected output:

Clean: asha.kumar@mail.com
Length: 19
Gmail user? false
Name part: asha.kumar

trim() removes spaces at both ends. toLowerCase() makes every letter small. The other methods measure, check, and cut the text.

Try This

Change the email to "ravi@gmail.com". Predict all four lines, then press Run.

Introduction to Strings

A string is a sequence of characters. It can hold a word, a sentence, a number written as text, or even nothing at all.

String name = "Meena";
String sentence = "Java is fun.";
String empty = "";

Strings are everywhere in real programs: names, passwords, messages, file names, and web addresses.

Each character in a string has a position called an index. Like arrays, the index starts at 0.

Index:   0   1   2   3   4
         M   e   e   n   a

String Immutability

Immutable means "cannot be changed".

Once a String is created, its characters can never change. Methods like toUpperCase() do not change the original. They return a new string.

toUpperCase returns a new string and leaves the original alone

public class Main {
    public static void main(String[] args) {
        String city = "pune";

        city.toUpperCase();
        System.out.println("After calling toUpperCase: " + city);

        city = city.toUpperCase();
        System.out.println("After storing the result: " + city);
    }
}

Expected output:

After calling toUpperCase: pune
After storing the result: PUNE

The first call made a new string, "PUNE", but nobody stored it. So it was thrown away, and city still pointed to "pune".

The second time, the new string was stored back in city. The variable now points to the new string. The old "pune" string itself never changed.

Why Strings Are Immutable

  • Safety. A string passed to a method cannot be changed behind your back.
  • Sharing. Many variables can safely share one string. This makes the String Pool possible.
  • Security. File paths and passwords cannot be changed after they are checked.

String Pool

The String Pool is a special area of memory where Java keeps string literals.

When you write a literal like "Java", Java first looks in the pool. If "Java" is already there, it reuses that same string. It does not make a second copy.

Think of a shared library book. If ten students want the same book, the library lends the same copy. It does not print ten copies.

This only works because strings are immutable. If one variable could change the shared string, every other variable would change too.

new String("Java") skips the pool. It always makes a brand-new object.

Literals share one pooled string, new does not

public class Main {
    public static void main(String[] args) {
        String a = "Java";
        String b = "Java";
        String c = new String("Java");

        System.out.println("a == b: " + (a == b));
        System.out.println("a == c: " + (a == c));
        System.out.println("a.equals(c): " + a.equals(c));
    }
}

Expected output:

a == b: true
a == c: false
a.equals(c): true

a and b point to the same pooled string, so == is true.

c is a separate object made with new, so a == c is false, even though the text is the same.

equals() compares the text itself, so it is true.

 String Pool                Rest of memory
┌──────────┐               ┌──────────┐
│  "Java"  │ ◄── a, b      │  "Java"  │ ◄── c
└──────────┘               └──────────┘

There is rarely a good reason to write new String("..."). Use a literal.

String Literals

A string literal is text written directly in the code, inside double quotes.

Some characters need an escape sequence, which is a backslash followed by a letter or symbol:

EscapeMeaning
\nNew line
\tTab
\"Double quote
\\Backslash

Text Blocks

For text that spans many lines, Java has text blocks. A text block starts and ends with three double quotes, """.

Escapes and a text block

public class Main {
    public static void main(String[] args) {
        System.out.println("Name:\tAsha");
        System.out.println("She said \"Hello\"");
        System.out.println("Path: C:\\Users\\Asha");

        String address = """
            12 Lake Road
            Chennai
            600001""";
        System.out.println(address);
    }
}

Expected output:

Name:	Asha
She said "Hello"
Path: C:\Users\Asha
12 Lake Road
Chennai
600001

The text block keeps its line breaks. Java removes the indentation that all lines share, so the address starts at the left edge.

String Formatting

Concatenation

Concatenation means joining strings together. You use the + operator, or the concat() method.

When either side of + is a String, Java turns the other side into text and joins them.

+ joins text, and order matters

public class Main {
    public static void main(String[] args) {
        String first = "Asha";
        String last = "Kumar";

        System.out.println(first + " " + last);
        System.out.println(first.concat(" ").concat(last));
        System.out.println("Score: " + 40 + 2);
        System.out.println("Score: " + (40 + 2));
        System.out.println(40 + 2 + " is the score");
    }
}

Expected output:

Asha Kumar
Asha Kumar
Score: 402
Score: 42
42 is the score

Java works from left to right.

  • In "Score: " + 40 + 2, the text comes first, so 40 and 2 are joined as text.
  • In 40 + 2 + " is the score", the two numbers come first, so they are added to make 42 before the text is joined.

Use brackets whenever you want maths inside a sentence.

+ can join a string with any value. Numbers and boolean values become their text form. Objects are turned into text with their toString() method. A null value becomes the word null.

Formatting Methods

Joining many pieces with + can get messy. Formatting methods let you write a template with placeholders, then fill them in.

  • String.format(template, values...) returns the formatted string.
  • System.out.printf(template, values...) prints it straight away.
  • "template".formatted(values...) does the same as String.format, in a shorter form.

Each placeholder starts with %:

PlaceholderUsed forExample output
%sAny value as textAsha
%dWhole numbers42
%.2fA decimal with 2 places3.50
%nA new line—
%5dA whole number, padded to 5 characters 42

Templates with placeholders

public class Main {
    public static void main(String[] args) {
        String item = "Notebook";
        int quantity = 3;
        double price = 45.5;

        String line = String.format("%s x %d = %.2f", item, quantity, quantity * price);
        System.out.println(line);

        System.out.printf("Total due: Rs. %.2f%n", quantity * price);

        String report = "%s scored %d%%".formatted("Ravi", 87);
        System.out.println(report);
    }
}

Output:

Notebook x 3 = 136.50
Total due: Rs. 136.50
Ravi scored 87%

%.2f always shows two decimal places, so 136.5 becomes 136.50.

%% prints a real percent sign, because a single % starts a placeholder.

The values fill the placeholders in order. The first value goes into the first placeholder.

String Class

String is a class in the java.lang package. Java imports java.lang for you, so you never need an import for String.

Because String is a class, every string is an object. That is why you can call methods on it with a dot, like name.length().

A few facts about the String class:

  • It is final, so no other class can extend it.
  • A String variable can be null, which means it points to no string at all. Calling a method on null stops the program with a NullPointerException.
  • An empty string "" is a real string with zero characters. It is not the same as null.

String Methods

The String class has many methods. Here are the ones you will use most.

Length and Characters

Measure the text and read single characters

public class Main {
    public static void main(String[] args) {
        String word = "Programming";

        System.out.println("Length: " + word.length());
        System.out.println("First letter: " + word.charAt(0));
        System.out.println("Last letter: " + word.charAt(word.length() - 1));
        System.out.println("Is empty? " + word.isEmpty());
        System.out.println("Is blank? " + "   ".isBlank());
    }
}

Expected output:

Length: 11
First letter: P
Last letter: g
Is empty? false
Is blank? true

charAt(index) returns one char. The last index is length() - 1, just like an array.

isBlank() is true for a string that is empty or contains only spaces.

Searching and Cutting

Find, check and cut parts of a string

public class Main {
    public static void main(String[] args) {
        String file = "report_2026_final.pdf";

        System.out.println(file.indexOf("_"));
        System.out.println(file.lastIndexOf("_"));
        System.out.println(file.contains("2026"));
        System.out.println(file.startsWith("report"));
        System.out.println(file.endsWith(".pdf"));
        System.out.println(file.substring(7, 11));
        System.out.println(file.substring(file.lastIndexOf(".") + 1));
    }
}

Expected output:

6
11
true
true
true
2026
pdf

indexOf returns the position of the first match, or -1 if there is none.

substring(7, 11) returns the characters from index 7 up to, but not including, index 11. With one argument, substring goes to the end of the string.

Changing Case, Spaces and Content

Remember: each of these returns a new string.

Every method here returns a new string

public class Main {
    public static void main(String[] args) {
        String raw = "  hello world  ";

        System.out.println("[" + raw.trim() + "]");
        System.out.println(raw.trim().toUpperCase());
        System.out.println(raw.replace("world", "Java").trim());
        System.out.println("ha".repeat(3));

        String csv = "Asha,Ravi,Meena";
        String[] names = csv.split(",");
        System.out.println(names.length + " names, second is " + names[1]);

        System.out.println(String.join(" | ", names));
    }
}

Expected output:

[hello world]
HELLO WORLD
hello Java
hahaha
3 names, second is Ravi
Asha | Ravi | Meena

split(",") breaks the text into an array at every comma. String.join does the opposite: it glues an array back together with a separator.

String Methods at a Glance

MethodReturnsExampleResult
length()Number of characters"Java".length()4
charAt(i)The character at index i"Java".charAt(1)'a'
indexOf(s)First position of s, or -1"Java".indexOf("v")2
substring(a, b)Characters from a up to b"Java".substring(1, 3)"av"
contains(s)Whether s appears"Java".contains("av")true
startsWith(s)Whether it begins with s"Java".startsWith("J")true
toUpperCase()All capitals"Java".toUpperCase()"JAVA"
toLowerCase()All small letters"Java".toLowerCase()"java"
trim()Without spaces at both ends" Java ".trim()"Java"
replace(a, b)Every a swapped for b"Java".replace("a", "o")"Jovo"
split(s)An array, broken at s"a,b".split(",")["a", "b"]
isEmpty()Whether the length is 0"".isEmpty()true
repeat(n)The text repeated n times"ab".repeat(2)"abab"

String Comparison

Comparing strings is one of the most common sources of bugs in Java.

equals()

equals() checks whether two strings hold the same text. This is almost always what you want.

equalsIgnoreCase()

equalsIgnoreCase() also compares the text, but treats capital and small letters as the same.

==

== checks whether two variables point to the same object in memory. It does not compare the text.

It may seem to work with literals, because of the String Pool. But text that comes from user input, a file, or a method like substring is often a different object. Then == gives false, even when the text matches.

compareTo()

compareTo() compares two strings in dictionary order. It returns:

  • a negative number if the first string comes first;
  • 0 if they are equal;
  • a positive number if the first string comes later.

Four ways to compare strings

public class Main {
    public static void main(String[] args) {
        String saved = "admin";
        String typed = "ADMIN".toLowerCase();

        System.out.println("equals: " + saved.equals(typed));
        System.out.println("==: " + (saved == typed));
        System.out.println("equalsIgnoreCase: " + "Chennai".equalsIgnoreCase("CHENNAI"));

        System.out.println("apple vs banana: " + "apple".compareTo("banana"));
        System.out.println("pear vs pear: " + "pear".compareTo("pear"));
        System.out.println("mango vs grape: " + "mango".compareTo("grape"));
    }
}

Expected output:

equals: true
==: false
equalsIgnoreCase: true
apple vs banana: -1
pear vs pear: 0
mango vs grape: 6

typed holds "admin", the same text as saved. But it was made at run time by toLowerCase(), so it is a separate object. equals says true, while == says false.

"apple" comes before "banana", so compareTo gives a negative number. Only the sign matters, not the exact value.

Always compare text with equals(). A safe habit is to put the known literal first: "admin".equals(input). That version never throws a NullPointerException, even when input is null.

StringBuilder

Every time you change a String, Java makes a new one. In a loop that adds text hundreds of times, that means hundreds of thrown-away strings.

A StringBuilder is a mutable (changeable) sequence of characters. It changes its own text in place, without making a new object each time.

Think of a whiteboard. You can add words, rub some out, and insert others, all on the same board.

StringBuilder changes its own text in place

public class Main {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello");

        sb.append(" World");
        System.out.println(sb);

        sb.insert(0, ">> ");
        System.out.println(sb);

        sb.replace(3, 8, "Hi");
        System.out.println(sb);

        sb.reverse();
        System.out.println(sb);

        System.out.println("Length: " + sb.length());
    }
}

Expected output:

Hello World
>> Hello World
>> Hi World
dlroW iH >>
Length: 11

Each call changes the same sb object. There is no need to write sb = sb.append(...).

MethodWhat it does
append(x)Adds x to the end
insert(i, x)Adds x at index i
delete(a, b)Removes characters from a up to b
replace(a, b, s)Replaces characters from a up to b with s
reverse()Reverses the text
toString()Returns the text as a normal String

Building Text in a Loop

This is the main reason StringBuilder exists.

Build a long string in a loop

public class Main {
    public static void main(String[] args) {
        StringBuilder line = new StringBuilder();

        for (int i = 1; i <= 5; i++) {
            line.append(i);
            if (i < 5) {
                line.append(" - ");
            }
        }

        String result = line.toString();
        System.out.println(result);
    }
}

Expected output:

1 - 2 - 3 - 4 - 5

toString() turns the finished builder into a normal String when you are done.

StringBuffer

StringBuffer has the same methods as StringBuilder. You use it the same way.

The difference is safety with threads. A thread is one path of work, and a program can run several at the same time.

  • StringBuffer is thread-safe. Only one thread can change it at a time.
  • StringBuilder is not thread-safe, but it is faster.

StringBuffer works just like StringBuilder

public class Main {
    public static void main(String[] args) {
        StringBuffer log = new StringBuffer();

        log.append("Start");
        log.append(" -> Load");
        log.append(" -> Save");
        log.append(" -> Done");

        System.out.println(log);
        System.out.println("Steps text length: " + log.length());
    }
}

Expected output:

Start -> Load -> Save -> Done
Steps text length: 29

For normal programs that use one thread, choose StringBuilder. Use StringBuffer only when several threads change the same text.

Strings vs StringBuilder

StringStringBuilderStringBuffer
Can it change?No (immutable)Yes (mutable)Yes (mutable)
A change createsA new objectNothing new, it edits itselfNothing new, it edits itself
Thread-safe?Yes, because it cannot changeNoYes
Speed for many changesSlowFastA little slower than StringBuilder
Best forFixed text, keys, labelsBuilding text in a loopBuilding text shared between threads

Easy Way to Remember: text that stays the same is a String. Text you build step by step is a StringBuilder.

Common mistakes

The following mistakes are common when working with strings. Each row shows what you see, why it happens and how to fix it.

SymptomCauseFix
A string looks unchanged after a method callThe new string was not storedAssign the result back: s = s.trim();
A match fails when the text looks the same== was used on stringsUse equals()
StringIndexOutOfBoundsExceptionAn index of length() or more was usedUse indexes from 0 to length() - 1
NullPointerExceptionA method was called on a null stringCheck for null, or put the literal first
Total: 55 instead of Total: 10Text came before the mathsPut the maths in brackets
char cannot be converted to StringSingle quotes were usedUse double quotes for a String

What to Remember

  • A String is immutable. Its methods return new strings, so store the result.
  • Literals are shared in the String Pool. new String(...) makes a separate object.
  • Join text with +, and use brackets for maths. Use String.format or printf for neat output.
  • length(), charAt, indexOf, substring, split, replace, and trim cover most daily string work.
  • Compare text with equals(), never with ==. Use compareTo() for dictionary order.
  • Use StringBuilder to build text step by step. Use StringBuffer only when threads share the text.

Next: DateTime