- Java String class has two substring methods – substring(int beginIndex) and substring(int beginIndex, int endIndex).
- These methods return the substring from this string.
- If the index values are invalid,
StringIndexOutOfBoundsException
is thrown. - The original string remains unchanged because strings are immutable in Java.
- Java String substring() methods call
Arrays.copyOfRange()
method, which further callsSystem.
arraycopy
()
method. - String class also has subSequence() method to create a substring. However, this method internally calls the substring() method. This method was added so that String can implement CharSequence interface.
- You should use the substring() method to create a substring and avoid using subSequence() method.
- These methods use the
new
operator to return the substring unless returning the same string. So the substring is created in the heap space. We can use the intern() method to move it to the string pool.
Table of Contents
Java String substring() Methods
Let’s look at both the substring() methods in more detail and with some code samples.
1. substring(int beginIndex)
The substring starts from the character at the given index and extends to the end of this string.
jshell> String str = "Hello Java";
str ==> "Hello Java"
jshell> String substring = str.substring(6);
substring ==> "Java"
This method throws StringIndexOutOfBoundsException if beginIndex is negative or greater than the length of this string.
jshell> String substring1 = str.substring(-6);
| Exception java.lang.StringIndexOutOfBoundsException: String index out of range: -6
| at String.substring (String.java:1846)
| at (#74:1)
jshell> String substring2 = str.substring(50);
| Exception java.lang.StringIndexOutOfBoundsException: String index out of range: -40
| at String.substring (String.java:1850)
| at (#75:1)
If we pass the index as 0, the reference to this string is returned.
jshell> String substring2 = str.substring(0);
substring2 ==> "Hello Java"
jshell> str == substring2
$105 ==> true
If we pass index as the length of this string, an empty string is returned.
jshell> String s = "Java String";
s ==> "Java String"
jshell> String s1 = s.substring(s.length());
s1 ==> ""
Here is a simple example to confirm that the substring is created in the heap space and not in the string pool.
jshell> String s1Pool = "Hello Java";
s1Pool ==> "Hello Java"
jshell> String s2Pool = "Java";
s2Pool ==> "Java"
jshell> String s3Heap = s1Pool.substring(6);
s3Heap ==> "Java"
jshell> s2Pool == s3Heap;
$88 ==> false
jshell> s2Pool.equals(s3Heap);
$89 ==> true
jshell> s3Heap = s3Heap.intern();
s3Heap ==> "Java"
jshell> s2Pool == s3Heap;
$91 ==> true
Notice that the == operator returns false in the first case, but it returns true after we use intern() method on the substring.
2. substring(int beginIndex, int endIndex)
The substring begins from the character at the beginIndex and extends to the character at (endIndex – 1). The length of the substring is (endIndex – beginIndex).
jshell> String str = "Java Python";
str ==> "Java Python"
jshell> String substring = str.substring(4, 8);
substring ==> " Pyt"
jshell> substring.length()
$94 ==> 4
This method throws StringIndexOutOfBoundsException for the following scenarios.
beginIndex
is negativeendIndex
is negativeendIndex
is greater than the length of this stringbeginIndex
is greater than theendIndex
jshell> String str = "JavaString.net";
str ==> "JavaString.net"
jshell> str.substring(-1, 5)
| Exception java.lang.StringIndexOutOfBoundsException: begin -1, end 5, length 14
| at String.checkBoundsBeginEnd (String.java:3410)
| at String.substring (String.java:1883)
| at (#96:1)
jshell> str.substring(1, -5)
| Exception java.lang.StringIndexOutOfBoundsException: begin 1, end -5, length 14
| at String.checkBoundsBeginEnd (String.java:3410)
| at String.substring (String.java:1883)
| at (#97:1)
jshell> str.substring(1, 50)
| Exception java.lang.StringIndexOutOfBoundsException: begin 1, end 50, length 14
| at String.checkBoundsBeginEnd (String.java:3410)
| at String.substring (String.java:1883)
| at (#98:1)
jshell> str.substring(5, 2)
| Exception java.lang.StringIndexOutOfBoundsException: begin 5, end 2, length 14
| at String.checkBoundsBeginEnd (String.java:3410)
| at String.substring (String.java:1883)
| at (#99:1)
jshell>
If we pass beginIndex as 0 and the endIndex as the length of this string, the reference to this string is returned.
jshell> String str = "Java";
str ==> "Java"
jshell> String substring = str.substring(0, str.length())
substring ==> "Java"
jshell> str == substring
$102 ==> true
If we pass the same value for beginIndex and endIndex, an empty string is returned provided the index values are valid.
jshell> String empty = "Hello".substring(2, 2);
empty ==> ""
jshell> String empty = "Hello".substring(20, 20);
| Exception java.lang.StringIndexOutOfBoundsException: begin 20, end 20, length 5
| at String.checkBoundsBeginEnd (String.java:3410)
| at String.substring (String.java:1883)
| at (#107:1)
The substring is created in the heap space, here is a simple code snippet to confirm this.
jshell> String s1 = "Hello Java";
s1 ==> "Hello Java"
jshell> String s2 = "Hello";
s2 ==> "Hello"
jshell> String s3 = s1.substring(0,5);
s3 ==> "Hello"
jshell> s2 == s3
$111 ==> false
Conclusion
Java String substring() methods are used to create a substring from this string. The method throws StringIndexOutOfBoundsException if the index values are invalid. You should use the substring() method rather than subSequence() method to create a substring.