The String.substring() method returns a new String that contains a sub-sequence of characters from the original string, defined by specified begin and end positions.
Half-Open Interval Slicing: Java extracts characters using the half-open interval [beginIndex, endIndex), where beginIndex is inclusive and endIndex is exclusive. To find delimiter landmarks, explore indexOf() and lastIndexOf(). For single character lookups, see charAt(), or measure string size with length().
Java provides two overloaded signatures for extracting substrings in java.lang.String:
// 2 Overloaded signatures of substring() in java.lang.String
public String substring(int beginIndex)
public String substring(int beginIndex, int endIndex)
| Signature | Parameters | Extracted Range |
|---|---|---|
substring(int beginIndex) |
beginIndex (inclusive) |
Extracts from beginIndex through to the end of the string (length()). |
substring(int beginIndex, int endIndex) |
beginIndex (inclusive), endIndex (exclusive) |
Extracts characters from beginIndex up to endIndex - 1. |
Because indexing starts at 0, landmark positions indicate exact character cut points:
String str = "Welcome to plus2net.com";
// 1. From index 11 to end of string
System.out.println(str.substring(11)); // plus2net.com
// 2. From index 11 up to index 15 (exclusive)
System.out.println(str.substring(11, 15)); // plus
// 3. From index 4 to end
System.out.println(str.substring(4)); // ome to plus2net.com
// 4. Single-character substring (index 4 to 5)
System.out.println(str.substring(4, 5)); // oTerminal Output:
plus2net.com
plus
ome to plus2net.com
o
A crucial rule in Java string manipulation is that endIndex is excluded. The length of the returned substring is always endIndex - beginIndex:
String word = "TELEPHONE";
// beginIndex=0, endIndex=4 -> extracts 4 characters: T-E-L-E
String prefix = word.substring(0, 4);
System.out.println("Prefix: " + prefix); // TELE
// Length of result is always: (endIndex - beginIndex)
int len = 4 - 0;
System.out.println("Length: " + prefix.length() + " == " + len); // 4 == 4Terminal Output:
Prefix: TELE
Length: 4 == 4
Selecting the optimal string extraction tool depends on whether you need a single character, a range, or an array of tokens:
| Method | Return Type | Operational Purpose |
|---|---|---|
str.substring(begin, end) |
String |
Extracts contiguous character sub-sequences by index bounds. |
str.charAt(index) |
char (primitive) |
Accesses a single 16-bit character with zero memory allocation. |
str.split(regex) |
String[] |
Tokenizes a string into multiple pieces around delimiter patterns. |
Java raises StringIndexOutOfBoundsException if any index is negative, if endIndex > length(), or if beginIndex > endIndex. Always validate dynamic bounds:
String text = "Java";
// RISKY: Accessing invalid index ranges
try {
System.out.println(text.substring(2, 6)); // endIndex 6 > length 4
} catch (StringIndexOutOfBoundsException e) {
System.out.println("Caught exception: " + e.getMessage());
}
// SAFE APPROACH: Verify bounds before slicing
int start = 1, end = 3;
if (start >= 0 && end <= text.length() && start <= end) {
System.out.println("Safe slice: " + text.substring(start, end)); // av
}Terminal Output:
Caught exception: Range [2, 6) out of bounds for length 4
Safe slice: av
Combining indexOf() delimiter search with substring() splits configuration keys from their values:
String param = "apiKey=xyz123secure";
int eqPos = param.indexOf('=');
if (eqPos != -1) {
String key = param.substring(0, eqPos);
String value = param.substring(eqPos + 1);
System.out.println("Key: " + key);
System.out.println("Value: " + value);
}Terminal Output:
Key: apiKey
Value: xyz123secure
Extracting trailing characters allows masking sensitive payment credentials while retaining trailing verification digits:
public class CreditCardMasker {
public static String maskCardNumber(String card) {
if (card == null || card.length() < 4) return card;
String lastFour = card.substring(card.length() - 4);
return "****-****-****-" + lastFour;
}
public static void main(String[] args) {
System.out.println(maskCardNumber("1234567890123456")); // ****-****-****-3456
}
}Terminal Output:
****-****-****-3456
Slicing the initial character separately from the remainder formats titles and usernames cleanly:
String name = "plus2net";
// Capitalize first letter: slice index 0..1, then slice index 1..end
String capitalized = name.substring(0, 1).toUpperCase() + name.substring(1);
System.out.println("Capitalized: " + capitalized);Terminal Output:
Capitalized: Plus2net
Assuming str.substring(0, 3) includes the character at index 3 is a common bug. It only extracts characters at indices 0, 1, and 2 (a total of 3 characters).
Unlike Python (where s[-4:] extracts the last 4 characters), passing negative numbers to Java's substring() immediately throws an exception. Use str.substring(str.length() - 4) instead.
You can compile and run this complete verification class locally in any Java IDE or environment:
public class StringSubstringFullDemo {
public static void main(String[] args) {
String data = "order:ORD-98765-CONFIRMED";
// 1. Extract prefix before colon
int colon = data.indexOf(':');
String prefix = data.substring(0, colon);
if (prefix.equals("order")) {
System.out.println("Check 1 Passed: Prefix 'order' extracted successfully.");
}
// 2. Extract order code using known indices
String code = data.substring(colon + 1, colon + 10);
if (code.equals("ORD-98765")) {
System.out.println("Check 2 Passed: Order code 'ORD-98765' extracted.");
}
// 3. Extract remaining suffix
String status = data.substring(colon + 11);
if (status.equals("CONFIRMED")) {
System.out.println("Check 3 Passed: Suffix 'CONFIRMED' extracted.");
}
System.out.println("All String.substring() tests passed successfully!");
}
}Terminal Output:
Check 1 Passed: Prefix 'order' extracted successfully.
Check 2 Passed: Order code 'ORD-98765' extracted.
Check 3 Passed: Suffix 'CONFIRMED' extracted.
All String.substring() tests passed successfully!
No. Strings in Java are completely immutable. substring() always creates and returns a brand-new String object.
Passing identical begin and end indices returns an empty string "", provided 0 <= k <= length().
No. Since Java 7u6, substring() copies characters into a new independent array, eliminating the old memory leak issue where a small substring retained a large parent array.
substring() returns a String, while subSequence() returns the broader CharSequence interface, internally delegating to substring().
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.