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
?
In charSequence you don't have very useful methods which are available for String. If you don't want to look in the documentation, type: obj. and str.
and see what methods your compilator offers you. That's the basic difference for me.
I know it a kind of obvious, but CharSequence is an interface whereas String is a concrete class :)
java.lang.String is an implementation of this interface...
General differences
There are several classes which implement the
CharSequence
interface besidesString
. Among these areStringBuilder
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 aString
will require conversion. So usingCharSequence
as an argument type in all the places where you don't care about the internals is prudent. However you should useString
as a return type if you actually return aString
, because that avoids possible conversions of returned values if the calling method actually does require aString
.Also note that maps should use
String
as key type, notCharSequence
, as map keys must not change. In other words, sometimes the immutable nature ofString
is essential.Specific code snippet
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 bothobj
andstr
are references to the same constant object. As aString
is immutable, this kind of sharing is all right.The
+
operator ofString
is compiled as invocations of variousStringBuilder.append
calls. So it is equivalent toI must confess I'm a bit surprised that my compiler
javac 1.6.0_33
compiles the+ obj
usingStringBuilder.append(Object)
instead ofStringBuilder.append(CharSequence)
. The former probably involves a call to thetoString()
method of the object, whereas the latter should be possible in a more efficient way. On the other hand,String.toString()
simply returns theString
itself, so there is little penalty there. SoStringBuilder.append(String)
might be more efficient by about one method invocation.Several things happen in your code:
That creates a
String
literal,"hello"
, which is aString
object. Being aString
, which implementsCharSequence
, it is also aCharSequence
. (you can read this post about coding to interface for example).The next line:
is a little more complex.
String
literals in Java are held in a pool (interned) so the"hello"
on this line is the same object (identity) as the"hello"
on the first line. Therefore, this line only assigns the sameString
literal tostr
.At this point, both
obj
andstr
are references to theString
literal"hello"
and are thereforeequals
,==
and they are both aString
and aCharSequence
.I suggest you test this code, showing in action what I just wrote:
tl;dr
One is an interface (
CharSequence
) while other is a concrete implementation of that interface (String
).As an interface, normally the
CharSequence
would be more commonly seen thanString
, but some twisted history resulted in the interface being defined years after the implementation. So in older APIs we often seeString
while in newer APIs we tend to seeCharSequence
used to define arguments and return types.Details
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
.Twisted History
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 andStringBuffer
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 theCharSequence
interface and retroactively implemented that interface on String and String Buffer, as well as adding another implementationCharBuffer
. Later in Java 5 they addedStringBuilder
, basically a unsynchronized and therefore somewhat faster version ofStringBuffer
.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 expectCharSequence
. But (a)String
seems to still dominate the mindspace, and (b) there may be some subtle technical issues when mixing the variousCharSequence
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 theCollection
orList
interfaces in place of theArrayList
orLinkedList
implementations.Interface Versus Class
The key difference about
CharSequence
is that it is an interface, not an implementation. That means you cannot directly instantiate aCharSequence
. Rather you instantiate one of the classes that implements that interface.For example, here we have
x
that looks like aCharSequence
but underneath is actually aStringBuilder
object.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.
There are some subtle differences between
"cat"
andnew String("cat")
as discussed in this other Question, but are irrelevant here.Class Diagram
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.
Text Blocks
Other than more and more emoji and other characters that have come with successive versions of Unicode support, in recent years not much has changed in Java for working with text… until Java 13.
Java 13 may offer a preview of the new feature: text blocks. This would make writing embedded code strings such as SQL more convenient. See JEP 355.
This effort was preceded by JEP 326: Raw String Literals (Preview).
CharSequence
is a contract (interface), andString
is an implementation of this contract.The documentation for
CharSequence
is: