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.
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.
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.
Difference between CharSequence interface and CharSequence key
Take a look at the JavaDocs for CharSequence: https://docs.oracle.com/javase/8/docs/api/java/lang/CharSequence.html
Under implementing classes, you will see
CharBuffer, Segment, String, StringBuffer, StringBuilder
So by defining Action as taking a CharSequence parameter, it means that you can use any of the CharSequence implementations above, or possibly create your own. It is a way to loosely couple classes / class dependencies and make code more reusable and durable.
equality check between CharSequence and String objects with possible null values in java
As far as I understand your question, it is this:
You have two objects, and you want to see if they're equal.
What we'd WANT to do is to use String.equalsIgnoreCase()
. It's literally precisely what you want.
If the CharSequence object is not null, it's pretty easy, because CharSequence.toString()
returns a string with the exact same characters in the exact same order.
charSequence.toString().equalsIgnoreCase(otherString);
Unfortunately this doesn't work. If the charsequence is null, then this throws a NullPointerException. So we need to see if the charsequence is null, and proceed from there.
public boolean compareCSAndString(CharSequence cs, String string) {
if(cs == null) {
// If both are null, then they're equal
return string == null;
}
else {
return cs.toString().equalsIgnoreCase(string);
}
}
This ticks all the boxes:
- It's case insensitive
- It handles null values
- It is clean and easy to read (no nested ifs)
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."
Related Topics
Noclassdeffounderror While Trying to Run My Jar with Java.Exe -Jar...What's Wrong
Java: String Concat VS Stringbuilder - Optimised, So What Should I Do
How to Convert a Date to Milliseconds
Possible to Use Two Java Classes with Same Name and Same Package
Building an Uberjar with Gradle
How to Change the Highlight Color of a Focused Jcombobox
In Java, How to Know Whether a Class Has Already Been Loaded
Java Fileinputstream Objectinputstream Reaches End of File Eof
Java Server with Multiclient Communication
Java Implementation of JSON to Xml Conversion
Is Concurrenthashmap Totally Safe
How to Create a New Packaging Type for Maven
How Do Format a Phone Number as a String in Java
A Rotated Square Panel in Java Gui
How to Use Selenium Webdriver Without Informing the Document That It Is Controlled by Webdriver