I read this previous post. Can any one say what the exact difference between CharSequence
and String is, other than the fact that String
implements CharSequence
and that String
is a sequence of character? For example:
CharSequence obj = "hello"; String str = "hello"; System.out.println("output is : " + obj + " " + str);
What happens when "hello" is assigned to obj
and again to str
?
A CharSequence is an Interface. String is an immutable sequence of characters and implements the CharSequence interface. CharSequence[] and String[] are just arrays of CharSequence and String respectively.
A CharSequence is a readable sequence of char values. This interface provides uniform, read-only access to many different kinds of char sequences. A char value represents a character in the Basic Multilingual Plane (BMP) or a surrogate. Refer to Unicode Character Representation for details.
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<String> interfaces.
To compare content a String str and CharSequence charSequence in Java, use String. contentEquals() method. Call contentEquals() method on the string str and pass the CharSequence object charSequence as argument. If the content of str equals the content of charSequence , then contentEquals() method returns true.
Every String object is a CharSequence. Every CharSequence can produce a String. Call CharSequence::toString. If the CharSequence happens to be a String, then the method returns a reference to its own object. In other words, every String is a CharSequence, but not every CharSequence is a String.
To compare content a String str and CharSequence charSequence in Java, use String.contentEquals () method. Call contentEquals () method on the string str and pass the CharSequence object charSequence as argument. If the content of str equals the content of charSequence, then contentEquals () method returns true.
Here, charSequence is instantiated with a String. Instantiating other implementations: 3. String 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<String> interfaces.
In Java, char is a primitive data type that is used to hold a single character. It means a single character of the UTF-16 character set. In comparison, String is a class that holds a sequence of characters and can be thought of as an array of chars.
There are several classes which implement the CharSequence
interface besides String
. Among these are
StringBuilder
for variable-length character sequences which can be modifiedCharBuffer
for fixed-length low-level character sequences which can be modifiedAny method which accepts a CharSequence
can operate on all of these equally well. Any method which only accepts a String
will require conversion. So using CharSequence
as an argument type in all the places where you don't care about the internals is prudent. However you should use String
as a return type if you actually return a String
, because that avoids possible conversions of returned values if the calling method actually does require a String
.
Also note that maps should use String
as key type, not CharSequence
, as map keys must not change. In other words, sometimes the immutable nature of String
is essential.
As for the code you pasted: simply compile that, and have a look at the JVM bytecode using javap -v
. There you will notice that both obj
and str
are references to the same constant object. As a String
is immutable, this kind of sharing is all right.
The +
operator of String
is compiled as invocations of various StringBuilder.append
calls. So it is equivalent to
System.out.println( (new StringBuilder()) .append("output is : ") .append((Object)obj) .append(" ") .append(str) .toString() )
I must confess I'm a bit surprised that my compiler javac 1.6.0_33
compiles the + obj
using StringBuilder.append(Object)
instead of StringBuilder.append(CharSequence)
. The former probably involves a call to the toString()
method of the object, whereas the latter should be possible in a more efficient way. On the other hand, String.toString()
simply returns the String
itself, so there is little penalty there. So StringBuilder.append(String)
might be more efficient by about one method invocation.
One is an interface (CharSequence
) while other is a concrete implementation of that interface (String
).
CharSequence animal = "cat" // `String` object presented as the interface `CharSequence`.
Just like ArrayList
is a List
, and HashMap
is a Map
, so too String
is a CharSequence
.
As an interface, normally the CharSequence
would be more commonly seen than String
, but some twisted history resulted in the interface being defined years after the implementation. So in older APIs we often see String
while in newer APIs we tend to see CharSequence
used to define arguments and return types.
Nowadays we know that generally an API/framework should focus on exporting interfaces primarily and concrete classes secondarily. But we did not always know this lesson so well.
The String
class came first in Java. Only later did they place a front-facing interface, CharSequence
.
A little history might help with understanding.
In its early days, Java was rushed to market a bit ahead of its time, due to the Internet/Web mania animating the industry. Some libraries were not as well thought-through as they should have been. String handling was one of those areas.
Also, Java was one of the earliest production-oriented non-academic Object-Oriented Programming (OOP) environments. The only successful real-world rubber-meets-the-road implementations of OOP before that was some limited versions of SmallTalk, then Objective-C with NeXTSTEP/OpenStep. So, many practical lessons were yet to be learned.
Java started with the String
class and StringBuffer
class. But those two classes were unrelated, not tied to each other by inheritance nor interface. Later, the Java team recognized that there should have been a unifying tie between string-related implementations to make them interchangeable. In Java 4 the team added the CharSequence
interface and retroactively implemented that interface on String and String Buffer, as well as adding another implementation CharBuffer
. Later in Java 5 they added StringBuilder
, basically a unsynchronized and therefore somewhat faster version of StringBuffer
.
So these string-oriented classes are a bit of a mess, and a little confusing to learn about. Many libraries and interfaces were built to take and return String
objects. Nowadays such libraries should generally be built to expect CharSequence
. But (a) String
seems to still dominate the mindspace, and (b) there may be some subtle technical issues when mixing the various CharSequence
implementations. With the 20/20 vision of hindsight we can see that all this string stuff could have been better handled, but here we are.
Ideally Java would have started with an interface and/or superclass that would be used in many places where we now use String
, just as we use the Collection
or List
interfaces in place of the ArrayList
or LinkedList
implementations.
The key difference about CharSequence
is that it is an interface, not an implementation. That means you cannot directly instantiate a CharSequence
. Rather you instantiate one of the classes that implements that interface.
For example, here we have x
that looks like a CharSequence
but underneath is actually a StringBuilder
object.
CharSequence x = new StringBuilder( "dog" ); // Looks like a `CharSequence` but is actually a `StringBuilder` instance.
This becomes less obvious when using a String literal. Keep in mind that when you see source code with just quote marks around characters, the compiler is translating that into a String object.
CharSequence y = "cat"; // Looks like a `CharSequence` but is actually a `String` instance.
There are some subtle differences between "cat"
and new String("cat")
as discussed in this other Question, but are irrelevant here.
This class diagram may help to guide you. I noted the version of Java in which they appeared to demonstrate how much change has churned through these classes and interfaces.
Other than adding more Unicode characters including a multitude of emoji, in recent years not much has changed in Java for working with text. Until text blocks.
Text blocks are a new way of better handling the tedium of string literals with multiple lines or character-escaping. This would make writing embedded code strings such as HTML, XML, SQL, or JSON much more convenient.
To quote JEP 378:
A text block is a multi-line string literal that avoids the need for most escape sequences, automatically formats the string in a predictable way, and gives the developer control over the format when desired.
The text blocks feature does not introduce a new data type. Text blocks are merely a new syntax for writing a String
literal. A text block produces a String
object, just like the conventional literal syntax. A text block produces a String
object, which is also a CharSequence
object, as discussed above.
To quote JSR 378 again…
Using "one-dimensional" string literals.
String query = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" + "WHERE \"CITY\" = 'INDIANAPOLIS'\n" + "ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";
Using a "two-dimensional" block of text
String query = """ SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB" WHERE "CITY" = 'INDIANAPOLIS' ORDER BY "EMP_ID", "LAST_NAME"; """;
Text blocks are found in Java 15 and later, per JEP 378: Text Blocks.
First previewed in Java 13, under JEP 355: Text Blocks (Preview). Then previewed again in Java 14 under JEP 368: Text Blocks (Second Preview).
This effort was preceded by JEP 326: Raw String Literals (Preview). The concepts were reworked to produce the Text Blocks feature instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With