Точная разница между CharSequence и String в java [дубликат]
этот вопрос уже есть ответ здесь:
- CharSequence против строки в Java? 9 ответов
- почему StringBuilder, когда есть строка? 10 ответов
- выбор между CharSequence и String для API [дубликат] 1 ответ
Я прочитал это предыдущий пост. Может ли кто-нибудь сказать, какая точная разница между CharSequence
и строка, кроме того, что String
осуществляет CharSequence
и String
- это последовательность символов? Для пример:
CharSequence obj = "hello";
String str = "hello";
System.out.println("output is : " + obj + " " + str);
что происходит, когда "привет" назначен obj
и снова str
?
8 ответов
общие различия
есть несколько классов, которые реализуют CharSequence
интерфейс кроме String
. Среди них
-
StringBuilder
для последовательностей символов переменной длины, которые могут быть изменены -
CharBuffer
для фиксированной длины низкоуровневых последовательностей символов, которые могут быть изменены
любой метод, который принимает CharSequence
может работать на все это одинаково хорошо. Любой метод, который принимает только String
потребует преобразования. Итак, используя CharSequence
как тип аргумента во всех местах, где вы не заботитесь о внутренних органах, разумно. Однако, вы должны использовать String
как тип возврата, если вы фактически возвращаете String
, потому что это позволяет избежать возможных преобразований возвращаемых значений, если вызывающий метод действительно требует String
.
Также обратите внимание, что карты должны использовать String
как тип ключа, а не CharSequence
, как карта ключи не должны меняться. Другими словами, иногда неизменная природа String
имеет важное значение.
конкретный фрагмент кода
что касается кода, который вы вставили: просто скомпилируйте его и посмотрите на байт-код JVM, используя javap -v
. Там вы заметите, что оба obj
и str
являются ссылками на один и тот же постоянный объект. Как String
является неизменным, этот вид обмена в порядке.
на +
оператор String
компилируется как призывы различных StringBuilder.append
звонки. Таким образом, это эквивалентно
System.out.println(
(new StringBuilder())
.append("output is : ")
.append((Object)obj)
.append(" ")
.append(str)
.toString()
)
я должен признаться, я немного удивлен, что мой компилятор javac 1.6.0_33
составляет + obj
используя StringBuilder.append(Object)
вместо StringBuilder.append(CharSequence)
. Первый, вероятно, включает в себя вызов toString()
метод объекта, тогда как последний должен быть возможен более эффективным способом. С другой стороны,--26--> просто возвращает String
сам, так что там мало штрафа. Так что StringBuilder.append(String)
может быть более эффективным, о один метод вызова.
tl; dr
One-это интерфейс (CharSequence
), а другой-конкретную реализацию этого интерфейса (String
).
CharSequence animal = "cat" // `String` object presented as the interface `CharSequence`.
как интерфейс, обычно CharSequence
было бы более часто видно, чем String
, но некоторая скрученная история привела к тому, что интерфейс был определен годами после реализация. Поэтому в более старых API мы часто видим String
в то время как в новых API мы склонны видеть CharSequence
используется для определения Аргументы и возвращаемые типы.
подробности
в настоящее время мы знаем, что обычно API/framework должен сосредоточиться на экспорте интерфейсов в первую очередь и конкретных классов во вторую очередь. Но мы не всегда так хорошо знали этот урок.
на String
класс пришел первым в Java. Только позже они разместили фронтальный интерфейс,CharSequence
.
Закрученная История
немного истории может помочь с пониманием.
In его первые дни Java был спешил на рынок немного раньше своего времени из-за Интернет/веб-мании, оживляющей отрасль. Некоторые библиотеки были не так хорошо продуманы, как следовало бы. Одной из таких областей была обработка строк.
кроме того, Java был одним из самых ранних ориентированных на производство неакадемических объектно-ориентированное программирование (ООП) средах. Единственными успешными реальными реализациями каучука-встреч-дороги ООП до этого были некоторые ограниченные версии SmallTalk, потом С С NeXTSTEP/OpenStep. Таким образом, многие практические уроки еще предстоит извлечь.
Java началась с String
класс а StringBuffer
класса. Но эти два класса не были связаны между собой, не были связаны друг с другом ни наследованием, ни интерфейсом. Позже команда Java признала, что должна была быть объединяющая связь между связанными строками реализации, чтобы сделать их взаимозаменяемыми. В Java 4 команда добавила CharSequence
интерфейс и ретроактивно реализован этот интерфейс на String и String Buffer, а также добавление другой реализации CharBuffer
. Позже, в Java 5 они добавили StringBuilder
, в основном несинхронизированная и, следовательно, несколько более быстрая версия StringBuffer
.
таким образом, эти строковые классы немного беспорядок, и немного запутанным, чтобы узнать о. Многие библиотеки и интерфейсы были созданы для take и return String
объекты. В настоящее время такие библиотеки, как правило, должны быть построены ожидать CharSequence
. Но (а)String
кажется, все еще доминирует в пространстве разума, и (Б) могут быть некоторые тонкие технические проблемы при смешивании различных CharSequence
реализаций. Оглядываясь назад, мы можем видеть, что все эти струнные вещи могли бы быть лучше обработаны, но вот мы здесь.
в идеале Java началась бы с интерфейс и / или суперкласс, который будет использоваться во многих местах, где мы сейчас используем String
, так же, как мы используем Collection
или List
интерфейсы вместо ArrayList
или LinkedList
реализаций.
Интерфейс И Класс
ключевая разница о CharSequence
- это интерфейс, а не реализация. Это означает, что вы не можете напрямую создать экземпляр CharSequence
. Скорее вы создаете экземпляр одного из классов, который реализует этот интерфейс.
например, здесь мы имеем x
вот такой CharSequence
но под ним на самом деле
CharSequence
договора (интерфейс), и String
это реализация настоящего Договора.
public final class String extends Object
implements Serializable, Comparable<String>, CharSequence
на документация на CharSequence
- это:
CharSequence-это читаемая последовательность значений char. Этот интерфейс обеспечивает равномерное, только для чтения доступ ко многим различным видам char последовательности. Значение char представляет символ в Basic Многоязычный самолет (BMP) или суррогат. См. Unicode Характер Представление для деталей.
кроме того, что строка реализует CharSequence и что строка является последовательностью символов.
некоторые вещи в коде:
CharSequence obj = "hello";
создает String
буквальный, "hello"
, который является String
"объект". Быть String
, который реализует CharSequence
, это CharSequence
. (вы можете читать этот пост о кодировании в интерфейс например).
следующий строка:
String str = "hello";
немного сложнее. String
литералы на Java хранятся в пуле (интернированы), поэтому "hello"
в этой строке находится тот же объект (идентификатор), что и "hello"
на первой линии. Поэтому эта строка присваивает только то же самое String
литерал str
.
в этот момент оба obj
и str
относятся к String
литерал и equals
, ==
и как String
и a CharSequence
.
предлагаю вам протестировать этот код, показав в действии то, что я только что написал:
public static void main(String[] args) {
CharSequence obj = "hello";
String str = "hello";
System.out.println("Type of obj: " + obj.getClass().getSimpleName());
System.out.println("Type of str: " + str.getClass().getSimpleName());
System.out.println("Value of obj: " + obj);
System.out.println("Value of str: " + str);
System.out.println("Is obj a String? " + (obj instanceof String));
System.out.println("Is obj a CharSequence? " + (obj instanceof CharSequence));
System.out.println("Is str a String? " + (str instanceof String));
System.out.println("Is str a CharSequence? " + (str instanceof CharSequence));
System.out.println("Is \"hello\" a String? " + ("hello" instanceof String));
System.out.println("Is \"hello\" a CharSequence? " + ("hello" instanceof CharSequence));
System.out.println("str.equals(obj)? " + str.equals(obj));
System.out.println("(str == obj)? " + (str == obj));
}
Я знаю, что это своего рода очевидно, но CharSequence-это интерфейс, тогда как String-конкретный класс:)
java.ленг.String является реализацией этого интерфейса...
рассмотрим UTF-8. В UTF-8 кодовые точки Unicode строятся из одного или нескольких байтов. Класс, инкапсулирующий массив байтов UTF-8, может реализовать интерфейс CharSequence, но, безусловно, не является строкой. Конечно, вы не можете передать массив байтов UTF-8, где ожидается строка, но вы, безусловно, можете передать класс оболочки UTF-8, который реализует CharSequence, когда контракт расслаблен, чтобы разрешить CharSequence. В моем проекте я разрабатываю класс под названием CBTF8Field (сжатая двоичная передача Формат-восемь бит), чтобы обеспечить сжатие данных для xml, и я хочу использовать интерфейс CharSequence для реализации преобразований из массивов байтов CBTF8 в/из символьных массивов (UTF-16) и байтовых массивов (UTF-8).
причина, по которой я пришел сюда, заключалась в том, чтобы получить полное представление о контракте подпоследовательности.
из API Java CharSequence:
CharSequence-это читаемая последовательность символов. Этот интерфейс обеспечивает единый доступ только для чтения ко многим различным типам последовательностей символов.
этот интерфейс затем используется строка, CharBuffer и StringBuffer чтобы сохранить согласованность для всех имен методов.
в charSequence у вас нет очень полезных методов, которые доступны для String. Если вы не хотите искать в документации, введите: параметр obj. и ул.
и посмотрите, какие методы предлагает вам ваш компилятор. Это основное различие для меня.