Java中的CharSequence VS String?

e-s*_*tis 404 java string charsequence

在Android中编程,大多数文本值都在预期中CharSequence.

这是为什么?有什么好处,使用CharSequence过的主要影响是String什么?

在使用它们和从一个转换到另一个时,主要的区别是什么,预期会出现什么问题?

Zar*_*nen 335

字符串是CharSequences,所以你可以使用字符串而不用担心.Android只是试图通过允许您指定其他CharSequence对象(如StringBuffers)来尝试提供帮助.

  • 但请记住来自`CharSequence` javadoc的这个警告:这个接口不会改进`equals`和`hashCode`方法的一般契约.因此,比较实现`CharSequence`的两个对象的结果通常是**undefined**.每个对象可以由不同的类实现,并且不能保证每个类能够测试其实例与另一个的实例是否相等.因此,将任意`CharSequence`实例用作集合中的元素或映射中的键是不合适的. (99认同)
  • 除非Android在回调中传递了CharSequence并且我需要一个String - 调用charSeq.toString(). (93认同)
  • @TrevorRobinson,所以设计bug首先在`Object`上有`equals` /`hashCode` .... (6认同)
  • @Pacerier:我认为这更多是一个实际限制.`CharSequence`是JDK 1.4中的一个改进,它为包含字符序列的对象引入了一个有限用途的通用接口.其中一些对象包含其他状态,因此将"Object.equals"定义为"包含相同的字符序列"可能没有意义.例如,NIO`CharBuffer`只将"position"和"limit"之间的字符暴露为`CharSequence`,尽管可能包含许多其他字符. (3认同)
  • @Pacerier:恕我直言在'Object`或`CharSequence`中没有设计错误,在实现之间不需要接口来提供相等的健全性.没有两个`Collection`需要在`Collection`界面之间提供相等,但如果他们选择的话,他们可以.恕我直言`CharSequence`应限于输入,并少用于返回类型. (3认同)

Bas*_*que 46

这个类图可以帮助您了解Java 7/8中字符串类型的大图.我不确定Android中是否存在所有这些内容,但总体情况可能仍然对您有用.

另请注意对已接受的答案所做的评论.所述CharSequence接口被改装到现有的类结构,所以有一些重要的细微之处(String&CharSequence).请注意在类/接口上标记的各种Java(1,2,4和5)版本 - 这些年来相当多的流失.理想情况下String,从一开始就会存在,但这就是生活.

各种与字符串相关的类和接口的图表

  • 这个图是你自己做的吗?想知道是否有针对不同数据结构的这些图表的目录。 (4认同)
  • @ user171943由我撰写,使用OmniGroup的[*OmniGraffle*](https://www.omnigroup.com/omnigraffle)应用程序手工制作. (4认同)

小智 37

我相信最好使用CharSequence.原因是String实现了CharSequence,因此您可以将String传递给CharSequence,但是您无法将CharSequence传递给String,因为CharSequence不会实现String.另外,在Android中,该EditText.getText()方法返回一个Editable,它还实现了CharSequence并且可以轻松地传递到一个,而不是很容易地传入一个String.CharSequence处理所有!

  • 你可以做`charSequence.toString()` (7认同)
  • @jorge:除非序列是可变的(或者出于任何原因需要复制字符才能生成不可变的字符串),否则效率相对较低。 (2认同)

Ita*_*man 23

通常,使用界面可以让您以最小的附带损害来改变实施方式.虽然java.lang.String非常受欢迎,但在某些情况下可能需要使用另一个实现.通过围绕CharSequences而不是字符串构建API,代码使人们有机会这样做.


Phi*_*llo 8

这几乎可以肯定是性能原因.例如,假设一个解析器通过一个包含字符串的500k ByteBuffer.

返回字符串内容有3种方法:

  1. 在解析时构建一个String [],一次一个字符.这将花费相当多的时间.我们可以使用==而不是.equals来比较缓存的引用.

  2. 在解析时使用偏移量构建一个int [],然后在get()发生时动态构建String.每个String都是一个新对象,因此没有缓存返回值并使用==

  3. 在解析时构建CharSequence [].由于没有存储新数据(除了偏移到字节缓冲区之外),解析比#1低得多.在get时,我们不需要构建一个String,因此get性能等于#1(比#2好得多),因为我们只返回对现有对象的引用.

除了使用CharSequence获得的处理增益之外,您还可以通过不复制数据来减少内存占用.例如,如果您有一个包含3段文本的缓冲区,并且想要返回所有3段或单个段落,则需要4个字符串来表示这一点.使用CharSequence,您只需要1个带数据的缓冲区,以及4个跟踪开始和长度的CharSequence实现实例.

  • 参考plz.听起来像随机猜测发生了什么.我也发现你的论点无效.一个人可能只是简单地将500k字节缓冲区存储为字符串,只返回子字符串,这是快速疯狂的,而且更为常见. (5认同)
  • @kritzikratzi - 从JDK7开始,String上的子串不再共享底层数组,并且不是"疯狂快速".它在子串的长度上花费O(N)时间,并且每次调用它时都会生成基础字符的副本(所以很多垃圾). (5认同)
  • 也许我错过了这一点,但这个答案是无稽之谈。**[`CharSequence`](https://developer.android.com/reference/java/lang/CharSequence.html) 是一个 *interface*** – 根据定义,它没有您讨论的任何实现细节,因为**它没有自己的实现**。`String` 是实现 `CharSequence` 接口的几个 *具体* 类之一。所以一个`String` *是*一个`CharSequence`。您可以比较 `String`、`StringBuffer` 和 `StringBuilder` 的性能细节,但不能比较 `CharSequence`。写“使用 CharSequence 获得的处理收益”是没有意义的。 (3认同)

Cry*_*pth 7

实际Android代码中出现的问题是将它们与CharSequence.equals进行比较是有效的,但不一定按预期工作.

EditText t = (EditText )getView(R.id.myEditText); // Contains "OK"
Boolean isFalse = t.getText().equals("OK"); // will always return false.
Run Code Online (Sandbox Code Playgroud)

比较应该由

("OK").contentEquals(t.GetText()); 
Run Code Online (Sandbox Code Playgroud)


Sur*_*gch 5

字符序列

A CharSequence是接口,而不是实际的类。接口只是类在实现接口时必须包含的一组规则(方法)。在Android中,a CharSequence是各种类型的文本字符串的保护伞。这是一些常见的:

(您可以在此处详细了解它们之间的区别。)

如果您有一个CharSequence对象,那么它实际上是实现的类之一的对象CharSequence。例如:

CharSequence myString = "hello";
CharSequence mySpannableStringBuilder = new SpannableStringBuilder();
Run Code Online (Sandbox Code Playgroud)

拥有像这样的通用伞类型的好处CharSequence是您可以用一种方法处理多种类型。例如,如果我有一个将a CharSequence作为参数的方法,则可以传入a String或a SpannableStringBuilder,它将处理其中一个。

public int getLength(CharSequence text) {
    return text.length();
}
Run Code Online (Sandbox Code Playgroud)

您可以说a String只是一种CharSequence。但是,与不同CharSequence,它是一个实际的类,因此您可以从中创建对象。因此,您可以这样做:

String myString = new String();
Run Code Online (Sandbox Code Playgroud)

但您不能这样做:

CharSequence myCharSequence = new CharSequence(); // error: 'CharSequence is abstract; cannot be instantiated
Run Code Online (Sandbox Code Playgroud)

由于CharSequence只是String符合条件的规则列表,因此您可以执行以下操作:

CharSequence myString = new String();
Run Code Online (Sandbox Code Playgroud)

这意味着,只要方法要求CharSequence,就可以给它一个String

String myString = "hello";
getLength(myString); // OK

// ...

public int getLength(CharSequence text) {
    return text.length();
}
Run Code Online (Sandbox Code Playgroud)

但是,事实并非如此。如果该方法采用String参数,则无法传递通常只被称为a的参数CharSequence,因为它实际上可能是a SpannableString或某种其他类型的CharSequence

CharSequence myString = "hello";
getLength(myString); // error

// ...

public int getLength(String text) {
    return text.length();
}
Run Code Online (Sandbox Code Playgroud)