246

How can I convert a Java CharSequence to a String?

slartidan
  • 20,403
  • 15
  • 83
  • 131
Belgi
  • 14,542
  • 22
  • 58
  • 68
  • Safest way: `String.valueOf(charSequence)`. [Here is the detailed answer](https://stackoverflow.com/questions/7707556/how-to-convert-charsequence-to-string/69848794#69848794) – Minhas Kamal Nov 05 '21 at 07:30

6 Answers6

389

By invoking its toString() method.

Returns a string containing the characters in this sequence in the same order as this sequence. The length of the string will be the length of this sequence.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • @TheOnlyAnil, does calling [`setText(CharSequence)`](http://developer.android.com/reference/android/widget/TextView.html#setText%28java.lang.CharSequence%29) not do what you need? – Mike Samuel May 04 '15 at 20:31
  • I want to make actionBar title clickable. – TheOnlyAnil May 04 '15 at 20:32
  • 1
    @TheOnlyAnil, maybe you should ask that as a question. Comments on an answer to a tangentially related question are not a good place to try and tease out your requirements. – Mike Samuel May 05 '15 at 14:38
  • Stackoverflow won't let me post any question. :/ btw I did that last night. Custom actionbar is the solution :) – TheOnlyAnil May 05 '15 at 15:23
  • 1
    By using the toString() method my CharSequence is displaying as, "[Ljava.lang.CharSequence;@26ae880a", not the text that was actually sent. toString() doesn't work. – Anton Jul 25 '18 at 12:41
  • 1
    @WillByers that output looks like the toString of a CharSequence array, not a CharSequence. – Mike Samuel Jul 25 '18 at 13:45
  • Wanted to upvote, but can't change 333 to 334, sorry! – Hibbem Mar 20 '20 at 16:44
  • 1
    @Hibbem someone else did it for you ;-) – logi-kal Jan 28 '21 at 11:06
  • @JamesFranken I'm having the same issue. I guess it's up to the implementer of the interface how this behaves. I solved it by using this instead: `String.join("", myCharSequence)` – dropbear Jan 11 '22 at 07:33
92

There is a subtle issue here that is a bit of a gotcha.

The toString() method has a base implementation in Object. CharSequence is an interface; and although the toString() method appears as part of that interface, there is nothing at compile-time that will force you to override it and honor the additional constraints that the CharSequence toString() method's javadoc puts on the toString() method; ie that it should return a string containing the characters in the order returned by charAt().

Your IDE won't even help you out by reminding that you that you probably should override toString(). For example, in intellij, this is what you'll see if you create a new CharSequence implementation: http://puu.sh/2w1RJ. Note the absence of toString().

If you rely on toString() on an arbitrary CharSequence, it should work provided the CharSequence implementer did their job properly. But if you want to avoid any uncertainty altogether, you should use a StringBuilder and append(), like so:

final StringBuilder sb = new StringBuilder(charSequence.length());
sb.append(charSequence);
return sb.toString();
Prudhvi
  • 2,276
  • 7
  • 34
  • 54
fragorl
  • 1,698
  • 15
  • 19
  • 12
    You shouldn't make mistakes/make your code worse because others might have made a mistake. – Lodewijk Apr 18 '13 at 02:03
  • 10
    return new StringBuilder(charSequence).toString(); is a single liner equivalent. – Gábor Lipták Sep 01 '15 at 12:48
  • 33
    **THIS ANSWER IS WRONG** The `CharSequence` interface explicitly defines `toString()` - the _implementor_ won't have missed this. The [javadoc](http://docs.oracle.com/javase/6/docs/api/java/lang/CharSequence.html#toString%28%29) states "Returns a string containing the characters in this sequence in the same order as this sequence. The length of the string will be the length of this sequence" since inception in [1.4](https://www.cs.duke.edu/csed/java/jdk1.4.2/docs/api/java/lang/CharSequence.html#toString%28%29). _People, please verify what you upvote_ – earcam Apr 16 '16 at 14:34
  • 1
    Incidentially `StringBuilder` implements `CharSequence`, so you're now _trusting_ the StringBuilder implementer did their job properly ツ – earcam Apr 16 '16 at 14:46
  • 1
    The difference being, it's relatively simple to inspect StringBuilder.java and satisfy yourself that StringBuilder.toString() is doing the correct thing (it is), while it's another matter to verify it is true for the limitless number of custom CharSequence implementations that do or could exist. – fragorl Apr 18 '16 at 04:27
  • 4
    This is silly. If you don't trust the implementer to follow the contract, all bets are off. Passing it as a parameter to `StringBuilder` could just as well fail to do what you expect. The same goes for any other interface, such as `List` or `Set`, in particular their `equals()` and `hashCode()` methods which will compile without overrides, but *must* be overridden according to the contract. – shmosel Jul 29 '16 at 20:37
  • 1
    Sure, I agree. However this is more about how the interface actually _hijacks_ the toString() method and usurps its original purpose entirely. Consider the documentation on the base method: "In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read." The intent of toString() is to provide a human-readable representation of an object, not a core piece of programmatic functionality. – fragorl Aug 01 '16 at 01:59
  • 4
    The fact that the interface does this is arguably a poor decision in that regard, and my answer simply highlights that this is an _easier than normal_ place for human error to occur. – fragorl Aug 01 '16 at 01:59
  • @shmosel in fact, an implementer is following interface contract, it implements given method to represent the object as a string, the problem is with its representation that sometimes has nothing to do with CharSequence, but description of the object (try adding CharSequence interface to the ArrayList, for example, you'll have default implementation of toString(), but it's not the one you want to have with CharSequence, even more, some tools won't even notify you that there is potential bug in your code if you won't implement that method explicitly) – Pavlus Aug 17 '17 at 12:10
  • @Pavlus I think you're missing the fact that `CharSequence` [overrides the contract](https://docs.oracle.com/javase/7/docs/api/java/lang/CharSequence.html#toString()) to return exactly what anyone would expect. – shmosel Aug 17 '17 at 17:01
  • @shmosel do I? What led you to such conclusion? – Pavlus Aug 20 '17 at 11:23
  • @Pavlus It sounds like you're trying to say the default `toString()` doesn't necessarily conform with what you'd expect from a `CharSequence`. If that's not it, I have no idea what you're saying. – shmosel Aug 20 '17 at 18:52
  • @shmosel yes, it doesn't. Default contract is to represent object as `String`, `CharSequence` specifies how exactly do that (it still represents the object but in the specified way) – Pavlus Aug 21 '17 at 08:54
  • this actually causes the string to be copied twice, once in the sb.append(), and another time in the sb.toString() – Solubris Nov 24 '20 at 16:59
  • The actual issue is that you can infer *meaning* just by having a string. There should be subtyping, when getting a `String` from a generic `Object` method: something like `HashCodeString` or `ObjectSystemString` or whatever. It's the return type from `toString` that is too generic, and exposes the side to ambiguity. Arguing on using a different object for generating the string, or on using a differently named method (that might *still* retain ambiguity) misses the point, IMHO. – Kamafeather Dec 30 '21 at 17:57
  • The expectation from `toString` on an `Object` and onto a `CharSequence` is to get returned a meaningful type. How the method is called is more for readability purposes; the name itself doesn't infer any guarantee about the context. What if I have a `SyntheticMaterial` with a `toString` method? What would *string* mean here? It might mean different things depending on the context (https://thexplorion.com/different-types-of-strings/). Focusing on the name is misleading; we should focus on the return types, to discern the use case. – Kamafeather Dec 30 '21 at 18:02
  • @earcam Your comment is wrong. Yes, `toString()` is defined in the interface, but that puts no obligation on the implementing classes to override it. It just says that is has to be implemented in the concrete class. Which it will be, because it's defined on Object, and everything is an object. See the example: https://ideone.com/fkvReI – Knox Aug 18 '22 at 21:58
  • @Knox, so the CharSequence explicitly declares toString and the associated JavaDoc states the expected behaviour - but your saying implementations may choose to ignore this as it won't be a compilation issue... Erm, those implementations are in violation of the expected behaviour, whether the compiler cares or not. – earcam Aug 24 '22 at 10:46
  • 1
    @earcam My problem was with saying "The CharSequence interface explicitly defines toString() - the _implementor_ **won't** have missed this." At least to me, that reads as if putting the method definition in the interface is what guarantees implementations will be forced to address it (override it), when in reality that's not the case. I interpret it that way because you said "won't", which to me means an impossibility (compiler error). I'm pointing it out because I've seen people make the assumption that putting toString() in an interface actually does require the implementations override it. – Knox Aug 24 '22 at 15:56
  • 1
    @earcam I agree with your conclusion that it's almost certainly unnecessary to be suspicious that the Javadocs weren't honored, especially in a java.lang class. I'm just trying to be careful about saying on a more general level that redefining methods from Object on an interface actually doesn't do anything besides create an opportunity to add comments through Javadocs – Knox Aug 24 '22 at 15:59
  • 1
    Also, not only is it *possible* for the implementer to have missed it (meaning "won't" is probably not an accurate way to describe this), but I think it's *trivial* to have missed it given what @Pavlus mentioned above. No errors, no warnings, and it works incorrectly (according to the Javadoc) by default since `toString()` is always implemented. – Knox Aug 24 '22 at 17:47
  • 1
    @Knox, (1/2) thank you for polite and intellect based argument (sincerely) - it sent me on a long tangent til sleep/forced-browser reset... Sharing rabbit-hole; 6y after my "someone on teh internet is wrong" comment, and considering your **valid counter arguments**. IMO the **solution** is new compiler warnings; very unlikely future versions of Java will/can ever allow an iface to abstract a method mandated to extend Object. So the only `java.lang` v8+ "fix" would be to redefine as default method that throws.. yuk + breaking change – earcam Sep 09 '22 at 20:29
  • 1
    @Knox, (2/2) solution via javac WDYT? I rabbit-holed searching for other soft-fails that a compiler could/should pick up - some at least current JDK err/warn codebase can certainly handle... When javac warnings raised as errors, this would meet both our concerns (implementations not assumed to follow weak JavaDoc contracts and consumers not needing to tediously guard) It is 1) an implementor's easy mistake, 2) exasperated by a language design fail - strongly typed, compiled language can resolve lang-fail. – earcam Sep 09 '22 at 20:33
30

You can directly use String.valueOf()

String.valueOf(charSequence)

Though this is same as toString() it does a null check on the charSequence before actually calling toString.

This is useful when a method can return either a charSequence or null value.

Abhishek Batra
  • 1,539
  • 1
  • 18
  • 45
14

The Safest Way

String string = String.valueOf(charSequence);

Let's Dive Deep

There are 3 common ways that we can try to convert a CharSequence to String:

  1. Type Casting: String string = (String) charSequence;
  2. Calling toString(): String string = charSequence.toString();
  3. String.valueOf() Method: String string = String.valueOf(charSequence);

And if we run these where CharSequence charSequence = "a simple string"; then all 3 of them will produce the expected result.

The problem happens when we are not sure about the nature of the CharSequence. In fact, CharSequence is an interface that several other classes implement, like- String, CharBuffer, StringBuffer, etc. So, converting a String to a CharSequence is a straightforward assignment operation, no casting or anything is required. But, for the opposite, Upcasting, it is not true.

If we are sure that the CharSequence is actually an object of String, only then we can use option 1- Type Casting. Otherwise, we will get a ClassCastException. Option 2 and 3 are safe in this case.

On the other side, if the CharSequence is null then option 2, calling toString(), will give a NullPointerException.

Now internally, String.valueOf() method calls the toString() method after doing a null check. So, it is the safest way. JavaDoc:

if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.


Please be aware: If CharSequence is null then String.valueOf() method return the string- "null", not null value.

Minhas Kamal
  • 20,752
  • 7
  • 62
  • 64
1

If you want to convert an array of CharSequence, You can simply do this and can also be store it in a String[] variable.

CharSequence[] textMsgs = (CharSequence[])sbm.getNotification().extras.get(Notification.EXTRA_TEXT_LINES);
if (textMsgs != null) {
   for (CharSequence msg : textMsgs) {
       Log.e("Msg", msg.toString());
   }
}
Gaur 97
  • 73
  • 5
0

Also you can une Stringbuilder.

new StringBuilder(charSequence).toString();