Pergunta

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)?

Foi útil?

Solução

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

Outras dicas

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.

Java CharSequence is an interface. As the API says, CharSequence has been implemented in CharBuffer, Segment, String, StringBuffer, StringBuilder classes. So if you want to access or accept your API from all these classes thenCharSequence is your choice. If not then String is very good for a public API because it is very easy & everybody knows about it. Remember CharSequence only gives you 4 method, so if you are accepting a CharSequence object through a method, then your input manipulation ability will be limited.

If a parameter is conceptually a sequence of chars, use CharSequence.

A string is technically a sequence of chars, but most often we don't think of it like that; a string is more atomic / holistic, we don't usually care about individual chars.

Think about int - though an int is technically a sequence of bits, we don't usually care about individual bits. We manipulate ints as atomic things.

So if the main work you are going to do on a parameter is to iterate through its chars, use CharSequence. If you are going to manipulate the parameter as an atomic thing, use String.

You can implement CharSequenceto hold your passwords, because the usage of String is discouraged for that purpose. The implementation should have a dispose method that wipes out the plain text data.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top