CharSequence VS String in Java?
Strings are CharSequences, so you can just use Strings and not worry. Android is merely trying to be helpful by allowing you to also specify other CharSequence objects, like StringBuffers.
Exact difference between CharSequence and String in java
General differences
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 modified
Any 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.
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 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.
Choosing between CharSequence and String for an API
Quoting CharSequence
Javadoc:
This interface does not refine the general contracts of the
equals
andhashCode
methods. The result of testing two objects that implementCharSequence
for equality is therefore, in general, undefined. Each object may be implemented by a different class, and there is no guarantee that each class will be capable of testing its instances for equality with those of the other. It is therefore inappropriate to use arbitraryCharSequence
instances as elements in a set or as keys in a map.
Hence IMO We must think twice before using CharSequnce as a replacement for String.
Difference Between StringBuffer(String str) and StringBuffer(CharSequence chars)
A CharSequence
is an interface; it happens that String
implements it.
This means that for instance, when you call .charAt()
on a String
, what is really called is the implementation of String
for this method of CharSequence
.
As you can see from the javadoc of CharSequence
, not many classes in the JDK actually implement this interface.
As to why two constructors, StringBuffer
dates back to Java 1.0 and CharSequence
appears in 1.4 only; however, this is also the case that StringBuilder
(which you should use, really, instead of StringBuffer
) has two constructors (one with a CharSequence
as an argument, another with a String
as an argument), so there are probably optimizations implied when a String
is passed as an argument. As to what such optimizations could be, well, it is a case of "Use The Source, Luke"(tm).
As an example of a CharSequence
implementation which is not in the JDK, you can for example see one of my projects: largetext. Note that among other things, generating a Matcher
from a Pattern
uses a CharSequence
and not a String
as an argument; and since String
implements CharSequence
, well, passing a String
as an argument works.
When to use CharSequence in an API
CharSequence
is rarely used in general purpose libraries. It should usually be used when your main use case is string handling (manipulation, parsing, ...).
Generally speaking you can do anything with a CharSequence
that you could do with a String
(trivially, since you can convert every CharSequence
into a String
). But there's one important difference: A CharSequence
is not guaranteed to be immutable! Whenever you handle a String
and inspect it at two different points in time, you can be sure that it will have the same value every time.
But for a CharSequence
that's not necessarily true. For example someone could pass a StringBuilder
into your method and modify it while you do something with it, which can break a lot of sane code.
Consider this pseudo-code:
public Object frobnicate(CharSequence something) {
Object o = getFromCache(something);
if (o == null) {
o = computeValue(something);
putIntoCache(o, something);
}
return o;
}
This looks harmless enough and if you'd had used String
here it would mostly work (except maybe that the value might be calculated twice). But if something
is a CharSequence
then its content could change between the getFromCache
call and the computeValue
call. Or worse: between the computeValue
call and the putIntoCache
call!
Therefore: only accept CharSequence
if there are big advantages and you know the drawbacks.
If you accept CharSequence
you should document how your API handles mutable CharSequence
objects. For example: "Modifying an argument while the method executes results in undefined behaviour."
why charsequence, instead of string?
But you can use a String[]
here, too.
CharSequence is an interface that String implements.
Related Topics
Java Regex for Support Unicode
Java Reflection: How to Get the All Getter Methods of a Java Class and Invoke Them
Sum Values from Specific Field of the Objects in a List
How to Create a Java 8 Localdate from a Long Epoch Time in Milliseconds
Persistent Httpurlconnection in Java
How to Draw an Image Over Another Image
How to Configure JPA for Testing in Maven
How Could I Add a Simple Delay in a Java Swing Application
How to Make a Jbutton in a Jtable Cell Click-Able
Copy All Values from Fields in One Class to Another Through Reflection
How Much Data Can a List Can Hold at the Maximum
Simpledateformat Parse Loses Timezone
Obtaining the Array Class of a Component Type
Java Fileoutputstream Create File If Not Exists
Call a Method of Subclass in Java
How to Fix "The Expression of Type List Needs Unchecked Conversion...'