[java] CharSequence VS String in Java?

Programming in Android, most of the text values are expected in CharSequence.

Why is that? What is the benefit, and what are the main impacts of using CharSequence over String?

What are the main differences, and what issues are expected, while using them, and converting from one to another?

This question is related to java string charsequence

The answer is


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.


CharSequence = interface
String = concrete implementation

You said:

converting from one to another

There is no converting from String.

  • 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.

Programming to an interface

Programming in Android, most of the text values are expected in CharSequence.

Why is that? What is the benefit, and what are the main impacts of using CharSequence over String?

Generally, programming to an interface is better than programming to concrete classes. This yields flexibility, so we can switch between concrete implementations of a particular interface without breaking other code.

When developing an API to be used by various programmers in various situations, write your code to give and take the most general interfaces possible. This gives the calling programmer the freedom to use various implementations of that interface, whichever implementation is best for their particular context.

For example, look at the Java Collections Framework. If your API gives or takes an ordered collection of objects, declare your methods as using List rather than ArrayList, LinkedList, or any other 3rd-party implementation of List.

When writing a quick-and-dirty little method to be used only by your code in one specific place, as opposed to writing an API to be used in multiple places, you need not bother with using the more general interface rather than a specific concrete class. But even then, it does to hurt to use the most general interface you can.

What are the main differences, and what issues are expected, while using them,

  • With a String you know you have a single piece of text, entirely in memory, and is immutable.
  • With a CharSequence, you do not know what the particular features of the concrete implementation might be.

The CharSequence object might represent an enormous chunk of text, and therefore has memory implications. Or may be many chunks of text tracked separately that will need to be stitched together when you call toString, and therefore has performance issues. The implementation may even be retrieving text from a remote service, and therefore has latency implications.

and converting from one to another?

You generally won't be converting back and forth. A String is a CharSequence. If your method declares that it takes a CharSequence, the calling programmer may pass a String object, or may pass something else such as a StringBuffer or StringBuilder. Your method's code will simply use whatever is passed, calling any of the CharSequence methods.

The closest you would get to converting is if your code receives a CharSequence and you know you need a String. Perhaps your are interfacing with old code written to String class rather than written to the CharSequence interface. Or perhaps your code will work intensively with the text, such as looping repeatedly or otherwise analyzing. In that case, you want to take any possible performance hit only once, so you call toString up front. Then proceed with your work using what you know to be a single piece of text entirely in memory.

Twisted history

Note the comments made on the accepted Answer. The CharSequence interface was retrofitted onto existing class structures, so there are some important subtleties (equals() & hashCode()). Notice the various versions of Java (1, 2, 4 & 5) tagged on the classes/interfaces—quite a bit of churn over the years. Ideally CharSequence would have been in place from the beginning, but such is life.

My class diagram below may help you see the big picture of string types in Java 7/8. I'm not sure if all of these are present in Android, but the overall context may still prove useful to you.

diagram of various string-related classes and interfaces


I believe it is best to use CharSequence. The reason is that String implements CharSequence, therefore you can pass a String into a CharSequence, HOWEVER you cannot pass a CharSequence into a String, as CharSequence doesn't not implement String. ALSO, in Android the EditText.getText() method returns an Editable, which also implements CharSequence and can be passed easily into one, while not easily into a String. CharSequence handles all!


CharSequence is a readable sequence of char values which implements String. it has 4 methods

  1. charAt(int index)
  2. length()
  3. subSequence(int start, int end)
  4. toString()

Please refer documentation CharSequence documentation


CharSequence is an interface and String implements it. You can instantiate a String but you could not do that for CharSequence since it is an interface. You can find other implementations in CharSequence in the official Java website.


This is almost certainly performance reasons. For example, imagine a parser that goes through a 500k ByteBuffer containing strings.

There are 3 approaches to returning the string content:

  1. Build a String[] at parse time, one character at a time. This will take a noticeable amount of time. We can use == instead of .equals to compare cached references.

  2. Build an int[] with offsets at parse time, then dynamically build String when a get() happens. Each String will be a new object, so no caching returned values and using ==

  3. Build a CharSequence[] at parse time. Since no new data is stored (other than offsets into the byte buffer), the parsing is much lower that #1. At get time, we don't need to build a String, so get performance is equal to #1 (much better than #2), as we're only returning a reference to an existing object.

In addition to the processing gains you get using CharSequence, you also reduce the memory footprint by not duplicating data. For example, if you have a buffer containing 3 paragraphs of text, and want to return either all 3 or a single paragraph, you need 4 Strings to represent this. Using CharSequence you only need 1 buffer with the data, and 4 instances of a CharSequence implementation that tracks the start and length.


An issue that DO arise in practical Android code is that comparing them with CharSequence.equals is valid but does not necessarily work as intended.

EditText t = (EditText )getView(R.id.myEditText); // Contains "OK"
Boolean isFalse = t.getText().equals("OK"); // will always return false.

Comparison should be made by

("OK").contentEquals(t.GetText()); 

CharSequence

A CharSequence is an interface, not an actual class. An interface is just a set of rules (methods) that a class must contain if it implements the interface. In Android a CharSequence is an umbrella for various types of text strings. Here are some of the common ones:

(You can read more about the differences between these here.)

If you have a CharSequence object, then it is actually an object of one of the classes that implement CharSequence. For example:

CharSequence myString = "hello";
CharSequence mySpannableStringBuilder = new SpannableStringBuilder();

The benefit of having a general umbrella type like CharSequence is that you can handle multiple types with a single method. For example, if I have a method that takes a CharSequence as a parameter, I could pass in a String or a SpannableStringBuilder and it would handle either one.

public int getLength(CharSequence text) {
    return text.length();
}

String

You could say that a String is just one kind of CharSequence. However, unlike CharSequence, it is an actual class, so you can make objects from it. So you could do this:

String myString = new String();

but you can't do this:

CharSequence myCharSequence = new CharSequence(); // error: 'CharSequence is abstract; cannot be instantiated

Since CharSequence is just a list of rules that String conforms to, you could do this:

CharSequence myString = new String();

That means that any time a method asks for a CharSequence, it is fine to give it a String.

String myString = "hello";
getLength(myString); // OK

// ...

public int getLength(CharSequence text) {
    return text.length();
}

However, the opposite is not true. If the method takes a String parameter, you can't pass it something that is only generally known to be a CharSequence, because it might actually be a SpannableString or some other kind of CharSequence.

CharSequence myString = "hello";
getLength(myString); // error

// ...

public int getLength(String text) {
    return text.length();
}

In general using an interface allows you to vary the implementation with minimal collateral damage. Although java.lang.String are super popular it may be possible that in certain contexts one may want to use another implementation. By building the API around CharSequences rather than Strings the code gives one the opportunity to do that.