I'm designing a public interface (API) for a package. I wonder, should I use CharSequence
generally instead of String
. (I'm mainly talking about the public interfaces).
Are there any drawbacks of doing so? Is it considered a good practice?
What about using it for identifier-like purposes (when the value is matched against a set in a hash-based container)?
A CharSequence is an Interface. String is an immutable sequence of characters and implements the CharSequence interface. CharSequence[] and String[] are just arrays of CharSequence and String respectively.
A CharSequence is a readable sequence of char values. This interface provides uniform, read-only access to many different kinds of char sequences. A char value represents a character in the Basic Multilingual Plane (BMP) or a surrogate. Refer to Unicode Character Representation for details.
String is a sequence of characters in Java. It is an immutable class and one of the most frequently used types in Java. This class implements the CharSequence, Serializable, and Comparable<String> interfaces.
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."
This does depend on what you need, I'd like to state two advantages of String
, however.
From CharSequence
's documentation:
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 arbitrary CharSequence instances as elements in a set or as keys in a map.
Thus, whenever you need a Map
or reliable equals
/hashCode
, you need to copy instances into a String
(or whatever).
Moreover, I think CharSequence
does not explicitly mention that implementations must be immutable. You may need to do defensive copying which may slow down your implementations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With