What does String.substring exactly do in Java?

Learn what does string.substring exactly do in java? with practical examples, diagrams, and best practices. Covers java, string development techniques with visual explanations.

Understanding Java's String.substring() Method

Hero image for What does String.substring exactly do in Java?

Explore the functionality, usage, and common pitfalls of the String.substring() method in Java, including its behavior with indices and edge cases.

The String.substring() method is a fundamental utility in Java for extracting a portion of a string. It allows developers to create new strings from existing ones by specifying start and end indices. While seemingly straightforward, understanding its precise behavior, especially concerning index boundaries, is crucial to avoid common errors like IndexOutOfBoundsException.

How String.substring() Works

Java's String class provides two overloaded versions of the substring() method:

  1. public String substring(int beginIndex)
  2. public String substring(int beginIndex, int endIndex)

Both methods return a new string that is a substring of the original string. It's important to remember that strings in Java are immutable, so substring() always creates a new String object rather than modifying the original.

The substring(int beginIndex) Method

This version extracts a substring starting from the specified beginIndex and extending to the end of the original string. The character at beginIndex is included in the new substring.

Index Rules:

  • beginIndex must be greater than or equal to 0.
  • beginIndex must be less than or equal to the length of the string.

If beginIndex is equal to the length of the string, an empty string is returned. If beginIndex is less than 0 or greater than the string's length, an IndexOutOfBoundsException is thrown.

String original = "Hello World";
String sub1 = original.substring(6); // "World"
String sub2 = original.substring(0); // "Hello World"
String sub3 = original.substring(original.length()); // "" (empty string)

System.out.println(sub1); // Output: World
System.out.println(sub2); // Output: Hello World
System.out.println(sub3); // Output: (empty line)

Examples of substring(int beginIndex)

The substring(int beginIndex, int endIndex) Method

This more commonly used version extracts a substring starting from beginIndex and extending up to, but not including, the character at endIndex. This means the character at beginIndex is included, but the character at endIndex is not.

Index Rules:

  • beginIndex must be greater than or equal to 0.
  • endIndex must be less than or equal to the length of the string.
  • beginIndex must be less than or equal to endIndex.

If any of these conditions are violated, an IndexOutOfBoundsException is thrown. If beginIndex is equal to endIndex, an empty string is returned.

String original = "Java Programming";
String sub1 = original.substring(0, 4);  // "Java"
String sub2 = original.substring(5, 16); // "Programming"
String sub3 = original.substring(5, 5);  // "" (empty string)
String sub4 = original.substring(0, original.length()); // "Java Programming"

System.out.println(sub1); // Output: Java
System.out.println(sub2); // Output: Programming
System.out.println(sub3); // Output: (empty line)
System.out.println(sub4); // Output: Java Programming

Examples of substring(int beginIndex, int endIndex)

flowchart LR
    A["Original String: 'Hello World'"]
    B["substring(0, 5)"]
    C["substring(6)"]
    D["substring(6, 11)"]

    A --> B
    A --> C
    A --> D

    B --> B_Result["Result: 'Hello'"]
    C --> C_Result["Result: 'World'"]
    D --> D_Result["Result: 'World'"]

    subgraph Index Visualization
        idx0["H (0)"] --> idx1["e (1)"] --> idx2["l (2)"] --> idx3["l (3)"] --> idx4["o (4)"] --> idx5["  (5)"] --> idx6["W (6)"] --> idx7["o (7)"] --> idx8["r (8)"] --> idx9["l (9)"] --> idx10["d (10)"]
    end

    B_Result -- "Indices 0 to 4" --> idx0
    B_Result -- "" --> idx4
    C_Result -- "Indices 6 to 10" --> idx6
    C_Result -- "" --> idx10
    D_Result -- "Indices 6 to 10" --> idx6
    D_Result -- "" --> idx10

Visualizing substring() behavior with indices

Common Pitfalls and Best Practices

While substring() is powerful, incorrect usage can lead to runtime errors. Here are some points to consider:

  • IndexOutOfBoundsException: This is the most common error. Always ensure your beginIndex and endIndex are within the valid range 0 to string.length(). It's good practice to validate indices before calling substring().
  • Off-by-One Errors: Due to the exclusive nature of endIndex, it's easy to make off-by-one errors. Double-check your endIndex to ensure it correctly excludes the desired character.
  • Performance Considerations (Pre-Java 7 Update 6): In older Java versions, substring() could lead to memory leaks or inefficiencies because the new string shared the underlying character array of the original string. This meant a small substring could prevent a very large original string from being garbage collected. This behavior was changed in Java 7 Update 6 and later versions, where substring() now creates a completely new character array, thus avoiding this specific memory issue. For modern Java applications, this is generally not a concern, but it's good historical context.
String text = "Example";

// Correct usage
String subCorrect = text.substring(0, 3); // "Exa"

// Incorrect usage - will throw IndexOutOfBoundsException
try {
    String subError1 = text.substring(-1); // beginIndex < 0
} catch (IndexOutOfBoundsException e) {
    System.out.println("Error: " + e.getMessage());
}

try {
    String subError2 = text.substring(text.length() + 1); // beginIndex > length
} catch (IndexOutOfBoundsException e) {
    System.out.println("Error: " + e.getMessage());
}

try {
    String subError3 = text.substring(0, text.length() + 1); // endIndex > length
} catch (IndexOutOfBoundsException e) {
    System.out.println("Error: " + e.getMessage());
}

try {
    String subError4 = text.substring(3, 2); // beginIndex > endIndex
} catch (IndexOutOfBoundsException e) {
    System.out.println("Error: " + e.getMessage());
}

Demonstrating IndexOutOfBoundsException scenarios