1. Introduction
Simply put, CharSequence and String are two different fundamental concepts in Java.
In this quick article, we’re going to have a look at the differences between these types and when to use each one.
2. CharSequence
CharSequence is an interface that represents a sequence of characters. Mutability is not enforced by this interface. Therefore, both mutable and immutable classes implement this interface.
Of course, an interface can’t be instantiated directly; it needs an implementation to instantiate a variable:
CharSequence charSequence = "baeldung";
Here, charSequence is instantiated with a String. Instantiating other implementations:
CharSequence charSequence = new StringBuffer("baeldung");
CharSequence charSequence = new StringBuilder("baeldung");
3. String
A String is a sequence of characters in Java. It is an immutable class and one of the most frequently used types in Java. This class implements the CharSequence, Serializable, and Comparable
If we create a String object by assigning a literal String value, the JVM applies the String interning operation: If there is already a copy of the value in the String pool, the same copy will be used for the newly created String object. Otherwise, the JVM creates the value in the String pool.
That is to say, when creating two String variables using the same literal String values, these variables are the same object:
String string1 = "baeldung";
String string2 = "baeldung";
assertEquals(string1, string2);
assertSame(string1, string2);
However, *if we instantiate String objects using the constructor new String(“…”), even if their values are the same, each String object has its own memory region.* Therefore, they are different objects:
String string3 = new String("baeldung");
assertEquals(string1, string3);
assertNotSame(string1, string3);
As we can see, string3 has the same value as string1, but string3 and string1 are two different objects.
4. CharSequence vs. String
Let’s compare the differences and commonalities of CharSequence and String. They both reside in the same package named java.lang., but the former is an interface and the latter is a concrete class. Moreover, the String class is immutable.
In the following example, each sum operation creates another instance, increases the amount of data stored, and returns the most recently created String:
@Test
public void givenString_whenAppended_thenUnmodified() {
String test = "a";
int firstAddressOfTest = System.identityHashCode(test);
test += "b";
int secondAddressOfTest = System.identityHashCode(test);
assertNotEquals(firstAddressOfTest, secondAddressOfTest);
}
On the other hand, StringBuilder updates the already created String to hold the new value:
@Test
public void givenStringBuilder_whenAppended_thenModified() {
StringBuilder test = new StringBuilder();
test.append("a");
int firstAddressOfTest = System.identityHashCode(test);
test.append("b");
int secondAddressOfTest = System.identityHashCode(test);
assertEquals(firstAddressOfTest, secondAddressOfTest);
}
Another difference is that the interface does not imply a built-in comparison strategy, whereas the String class implements the Comparable
To compare two CharSequences, we can cast them to Strings and then subsequently compare them:
@Test
public void givenIdenticalCharSequences_whenCastToString_thenEqual() {
CharSequence charSeq1 = "baeldung_1";
CharSequence charSeq2 = "baeldung_2";
assertTrue(charSeq1.toString().compareTo(charSeq2.toString()) > 0);
}
5. Convert CharSequence to String
CharSequence is an interface implemented by several classes such as String, StringBuilder, and StringBuffer. So, converting a CharSequence to a String is not always as straightforward as it may seem.
In short, there are three common approaches to convert from a CharSequence to a String object. We can use type casting, call the toString() method, or the static method valueOf().
5.1. Using Type Casting
If we are sure that our CharSequence is an object of type String, then we can use implicit or explicit casting:
@Test
public void givenCharSequenceAsString_whenConvertingUsingCasting_thenCorrect() {
String expected = "baeldung";
CharSequence charSequence = "baeldung";
String explicitCastedString = (String) charSequence;
assertEquals(expected, charSequence);
assertEquals(expected, explicitCastedString);
}
Otherwise, we will get a ClassCastException exception:
@Test(expected = ClassCastException.class)
public void givenCharSequenceAsStringBuiler_whenConvertingUsingCasting_thenThrowException() {
CharSequence charSequence = new StringBuilder("baeldung");
String castedString = (String) charSequence;
}
The cause behind the exception is that the CharSequence object is of type StringBuilder and not String.
5.2. Using toString() Method
toString() is another option to consider when converting CharSequence to String. So, let’s see it in action:
@Test
public void givenCharSequence_whenConvertingUsingToString_thenCorrect() {
String expected = "baeldung";
CharSequence charSequence1 = "baeldung";
CharSequence charSequence2 = new StringBuilder("baeldung");
assertEquals(expected, charSequence1.toString());
assertEquals(expected, charSequence2.toString());
}
This approach works even if the charSequence2 is not originally a String.
However, we need to make sure that our CharSequence is not null. Otherwise, a NullPointerException will be thrown.
5.3. Using valueOf() Method
The static valueOf() method, belonging to the String class, provides a versatile way to convert various data types, including CharSequence, into a string:
@Test
public void givenCharSequence_whenConvertingUsingValueOf_thenCorrect() {
String expected = "baeldung";
CharSequence charSequence1 = "baeldung";
CharSequence charSequence2 = new StringBuilder("baeldung");
CharSequence charSequence3 = null;
assertEquals(expected, String.valueOf(charSequence1));
assertEquals(expected, String.valueOf(charSequence2));
assertEquals("null", String.valueOf(charSequence3));
}
Here, we used the variant String valueOf(Object obj), which calls obj.toString() if the passed object is not null and returns the value “null” otherwise.
6. Conclusion
We usually use String in the places where we’re not sure what to use for char sequences. However, in some cases, StringBuilder and StringBuffer can be more appropriate.
You can find more information in JavaDocs about CharSequence and String.
And, as always, the implementation of all these examples and code snippets can be found over on GitHub.