CharSequence VS字符串在Java?

在Android中编程,大多数文本值都在CharSequence中。

为什么呢?与String相比,使用CharSequence的好处是什么?主要影响是什么?

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

141083 次浏览

字符串是字符序列,所以你可以只使用字符串,不用担心。Android只是试图通过允许你指定其他CharSequence对象来提供帮助,比如stringbuffer。

一般来说,使用接口允许您以最小的附带损害改变实现。虽然java.lang.String非常流行,但在某些情况下,人们可能想使用另一种实现。通过围绕CharSequences而不是string构建API,代码提供了这样做的机会。

我认为最好使用CharSequence。原因是String实现了CharSequence,因此你可以传递一个String到一个CharSequence,然而你不能传递一个CharSequence到一个String,因为CharSequence不实现String。另外,在Android中EditText.getText()方法返回一个可编辑对象,它也实现了CharSequence,可以很容易地传递给CharSequence,而不容易传递给String。CharSequence处理所有!

这几乎肯定是性能方面的原因。例如,假设一个解析器通过一个包含字符串的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实现实例来跟踪开始和长度。

在实际的Android代码中出现的一个问题是将它们与CharSequence进行比较。Equals是有效的,但不一定像预期的那样工作。

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

应由

("OK").contentEquals(t.GetText());

CharSequence = interface
String =具体实现

  • CharSequence接口
  • 几个类实现此接口。
    • String就是这样一个类,是CharSequence的具体实现。
    • 李< / ul > < / >

    你说:

    从一个转换到另一个

    没有从String进行转换。

    • 每个String对象CharSequence
    • 每个CharSequence都可以产生一个StringCharSequence::toString打电话。如果CharSequence恰好是String,则该方法返回对自己对象的引用。

    换句话说,每个String都是CharSequence,但并不是每个CharSequence都是String

    编程到接口

    在Android中编程,大多数文本值都在CharSequence中。

    为什么呢?使用CharSequence而不是String的好处是什么,主要影响是什么?

    通常,面向接口编程比面向具体类编程更好。这产生了灵活性,因此我们可以在特定接口的具体实现之间切换,而不会破坏其他代码。

    当开发一个API供各种程序员在各种情况下使用时,编写代码尽可能给出和接受最通用的接口。这使得调用程序可以自由地使用该接口的各种实现,无论哪种实现最适合其特定上下文。

    例如,查看Java集合框架。如果你的API给出或接受一个有序的对象集合,将你的方法声明为使用List而不是ArrayListLinkedList或任何其他List的第三方实现。

    当编写一个快速而肮脏的小方法只供您的代码在一个特定的地方使用时,而不是编写一个API用于多个地方时,您不需要使用更通用的接口而不是特定的具体类。但即便如此,使用最通用的界面也会造成伤害。

    在使用它们时,主要的区别是什么,预期会出现什么问题,

    • 使用String,你知道你有一个单独的文本,完全在内存中,并且是不可变的。
    • 使用CharSequence,你不知道具体实现的具体特性可能是什么。

    CharSequence对象可能表示一个巨大的文本块,因此有内存影响。或者可能有许多单独跟踪的文本块,在调用toString时需要将它们拼接在一起,因此存在性能问题。实现甚至可能从远程服务检索文本,因此存在延迟问题。

    从一个转换到另一个?

    你通常不会来回转换。A String A CharSequence。如果你的方法声明它接受一个CharSequence对象,调用的程序员可以传递一个String对象,或者传递其他对象,如StringBufferStringBuilder。方法的代码将简单地使用传递的任何东西,调用任何CharSequence方法。

    最接近转换的情况是你的代码接收到一个CharSequence,而你知道你需要一个String。也许你正在使用编写到String类的旧代码,而不是编写到CharSequence接口的旧代码。或者,您的代码可能会大量处理文本,例如重复循环或进行其他分析。在这种情况下,你希望任何可能的性能损失都只发生一次,所以你预先调用toString。然后继续你的工作,使用你所知道的一段完全在内存中的文本。

    扭曲的历史

    注意在接受的答案上所做的注释。CharSequence接口被改造到现有的类结构上,因此有一些重要的微妙之处(equals() &hashCode())。注意Java的不同版本(1,2,4 &5)标记在类/接口上——多年来相当多的变动。理想情况下,CharSequence应该从一开始就存在,但这就是生活。

    下面的类图可以帮助您了解Java 7/8中字符串类型的总体情况。我不确定是否所有这些都存在于Android中,但总体上下文可能仍然对你有用。

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

CharSequence是一个可读的字符值序列,它实现了String。它有4个方法

  1. charAt (int指数)
  2. 长度()
  3. 子序列(int start, int end)
  4. toString ()

请参考文档CharSequence进行文档

CharSequence是一个接口,String实现了它。你可以实例化一个String,但你不能为CharSequence这样做,因为它是一个接口。你可以在Java官方网站上找到CharSequence中的其他实现。

CharSequence进行

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

(你可以在这里阅读更多关于这些之间的区别。)

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

CharSequence myString = "hello";
CharSequence mySpannableStringBuilder = new SpannableStringBuilder();

拥有像CharSequence这样的通用伞形类型的好处是,你可以用一个方法处理多个类型。例如,如果我有一个以CharSequence为参数的方法,我可以传入StringSpannableStringBuilder,它可以处理其中任何一个。

public int getLength(CharSequence text) {
return text.length();
}

字符串

你可以说String只是一种CharSequence。然而,与CharSequence不同的是,它是一个实际的类,所以你可以从它创建对象。所以你可以这样做:

String myString = new String();

但你不能这样做:

CharSequence myCharSequence = new CharSequence(); // error: 'CharSequence is abstract; cannot be instantiated

因为CharSequence只是一个String所遵循的规则列表,你可以这样做:

CharSequence myString = new String();

这意味着每当一个方法请求CharSequence时,可以给它一个String

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


// ...


public int getLength(CharSequence text) {
return text.length();
}

然而,反过来就不对了。如果方法接受String参数,则不能传递给它通常只知道是CharSequence的值,因为它实际上可能是SpannableString或其他类型的CharSequence

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


// ...


public int getLength(String text) {
return text.length();
}