Когда использовать CharSequence в API

Я разрабатываю публичный интерфейс (API) для пакета. Интересно, следует ли использовать CharSequence вместо String. (Я в основном говорю об открытых интерфейсах).

Есть ли недостатки в этом? Является ли это хорошей практикой?

Как использовать его для целей, подобных идентификаторам (когда значение сопоставляется с набором в контейнере на основе хэша)?

Ответ 1

CharSequence редко используется в библиотеках общего назначения. Его обычно следует использовать, когда ваш основной вариант использования - обработка строк (манипуляция, разбор,...).

Вообще говоря, вы можете делать что-либо с CharSequence, которое вы могли бы сделать с помощью String (тривиально, так как вы можете конвертировать каждый CharSequence в String). Но существует одно важное различие: A CharSequence не гарантируется неизменным! Всякий раз, когда вы обрабатываете String и проверяете его в два разных момента времени, вы можете быть уверены, что он будет иметь одинаковое значение каждый раз.

Но для a CharSequence это не обязательно верно. Например, кто-то может передать StringBuilder в свой метод и изменить его, пока вы что-то делаете с ним, что может сломать много разумного кода.

Рассмотрим этот псевдокод:

public Object frobnicate(CharSequence something) {
  Object o = getFromCache(something);
  if (o == null) {
    o = computeValue(something);
    putIntoCache(o, something);
  }
  return o;
}

Это выглядит достаточно безвредным, и если бы вы использовали String здесь, он работал бы в основном (за исключением того, что значение могло быть рассчитано дважды). Но если something является CharSequence, то его содержимое может меняться между вызовом getFromCache и вызовом computeValue. Или еще хуже: между вызовом computeValue и вызовом putIntoCache!

Следовательно: только принять CharSequence, если есть большие преимущества, и вы знаете недостатки.

Если вы принимаете CharSequence, вы должны указать, как ваш API обрабатывает изменяемые объекты CharSequence. Например: "Изменение аргумента, когда метод выполняет результаты в undefined".

Ответ 2

Java CharSequence - это интерфейс. Как говорит API, CharSequence был реализован в классах CharBuffer, Segment, String, StringBuffer, StringBuilder. Поэтому, если вы хотите получить или принять свой API от all этих классов, тогда CharSequence - ваш выбор. Если нет, то String очень хорошо подходит для публичного API, потому что это очень легко, и все об этом знают. Помните, что CharSequence предоставляет только 4 метода, поэтому, если вы принимаете объект CharSequence с помощью метода, то ваша способность к обработке ввода будет ограничена.

Ответ 3

Это зависит от того, что вам нужно, однако я хотел бы указать два преимущества String.

Из CharSequence документация:

Каждый объект может быть реализован другим классом, и нет гарантировать, что каждый класс сможет проверить свои экземпляры для равенство с другим. Поэтому нецелесообразно использовать произвольные экземпляры CharSequence как элементы в наборе или как ключи в карта.

Таким образом, всякий раз, когда вам нужен Map или надежный equals/hashCode, вам нужно скопировать экземпляры в String (или что-то еще).

Более того, я думаю, что CharSequence явно не упоминает, что реализации должны быть неизменными. Вам может потребоваться защитное копирование, которое может замедлить ваши реализации.

Ответ 4

Если параметр концептуально представляет собой последовательность символов, используйте CharSequence.

Строка технически представляет собой последовательность символов, но чаще всего мы не думаем об этом; строка более атомарная/целостная, мы обычно не заботимся о отдельных символах.

Подумайте о int - хотя int - это технически последовательность бит, мы обычно не заботимся о отдельных битах. Мы манипулируем int как атомные вещи.

Итак, если основная работа, которую вы собираетесь делать по параметру, - это итерация по своим символам, используйте CharSequence. Если вы собираетесь манипулировать параметром как атомарная вещь, используйте String.

Ответ 5

Вы можете реализовать CharSequence для хранения ваших паролей, потому что использование String не рекомендуется для этой цели. Реализация должна иметь метод удаления, который уничтожает данные обычного текста.