Java中的CharSequence VS String?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1049228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:44:22  来源:igfitidea点击:

CharSequence VS String in Java?

javastringcharsequence

提问by e-satis

Programming in Android, most of the text values are expected in CharSequence.

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

Why is that? What is the benefit, and what are the main impacts of using CharSequenceover String?

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

What are the main differences, and what issues are expected, while using them, and converting from one to another?

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

采纳答案by Zarkonnen

Strings are CharSequences, so you can just use Strings and not worry. Android is merely trying to be helpful by allowing you to also specify other CharSequence objects, like StringBuffers.

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

回答by Itay Maman

In general using an interface allows you to vary the implementation with minimal collateral damage. Although java.lang.String are super popular it may be possible that in certain contexts one may want to use another implementation. By building the API around CharSequences rather than Strings the code gives one the opportunity to do that.

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

回答by Sham

I believe it is best to use CharSequence. The reason is that String implements CharSequence, therefore you can pass a String into a CharSequence, HOWEVER you cannot pass a CharSequence into a String, as CharSequence doesn't not implement String. ALSO, in Android the EditText.getText()method returns an Editable, which also implements CharSequence and can be passed easily into one, while not easily into a String. CharSequence handles all!

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

回答by Phil Lello

This is almost certainly performance reasons. For example, imagine a parser that goes through a 500k ByteBuffer containing strings.

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

There are 3 approaches to returning the string content:

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

  1. Build a String[] at parse time, one character at a time. This will take a noticeable amount of time. We can use == instead of .equals to compare cached references.

  2. Build an int[] with offsets at parse time, then dynamically build String when a get() happens. Each String will be a new object, so no caching returned values and using ==

  3. Build a CharSequence[] at parse time. Since no new data is stored (other than offsets into the byte buffer), the parsing is much lower that #1. At get time, we don't need to build a String, so get performance is equal to #1 (much better than #2), as we're only returning a reference to an existing object.

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

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

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

In addition to the processing gains you get using CharSequence, you also reduce the memory footprint by not duplicating data. For example, if you have a buffer containing 3 paragraphs of text, and want to return either all 3 or a single paragraph, you need 4 Strings to represent this. Using CharSequence you only need 1 buffer with the data, and 4 instances of a CharSequence implementation that tracks the start and length.

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

回答by Crypth

An issue that DO arise in practical Android code is that comparing them with CharSequence.equals is valid but does not necessarily work as intended.

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

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

Comparison should be made by

比较应该由

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

回答by Basil Bourque

CharSequence= interface
String= concrete implementation

CharSequence= 接口
String= 具体实现

You said:

你说:

converting from one to another

从一种转换到另一种

There is no converting from String.

没有从String.

  • Every Stringobject isa CharSequence.
  • Every CharSequencecan produce a String. Call CharSequence::toString. If the CharSequencehappens to be a String, then the method returns a reference to its own object.
  • 每个String对象都是一个CharSequence.
  • 每个都CharSequence可以产生一个String. 打电话CharSequence::toString。如果CharSequence恰好是 a String,则该方法返回对其自身对象的引用。

In other words, every Stringis a CharSequence, but not every CharSequenceis a String.

换句话说, everyString是 a CharSequence,但不是 everyCharSequence是 a String

Programming to an interface

编程到接口

Programming in Android, most of the text values are expected in CharSequence.

Why is that? What is the benefit, and what are the main impacts of using CharSequence over String?

在 Android 中编程,大部分文本值都在 CharSequence 中。

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

Generally, programming to an interface is better than programming to concrete classes. This yields flexibility, so we can switch between concrete implementations of a particular interface without breaking other code.

通常,对接口进行编程比对具体类进行编程要好。这产生了灵活性,因此我们可以在不破坏其他代码的情况下在特定接口的具体实现之间切换。

When developing an APIto be used by various programmers in various situations, write your code to give and take the most general interfaces possible. This gives the calling programmer the freedom to use various implementations of that interface, whichever implementation is best for their particular context.

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

For example, look at the Java Collections Framework. If your API gives or takes an ordered collection of objects, declare your methods as using Listrather than ArrayList, LinkedList, or any other 3rd-party implementation of List.

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

When writing a quick-and-dirty little method to be used only by your code in one specific place, as opposed to writing an API to be used in multiple places, you need not bother with using the more general interface rather than a specific concrete class. But even then, it does to hurt to use the most general interface you can.

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

What are the main differences, and what issues are expected, while using them,

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

  • With a Stringyou know you have a single piece of text, entirely in memory, and is immutable.
  • With a CharSequence, you do not know what the particular features of the concrete implementation might be.
  • 有了 aString你知道你有一段文本,完全在内存中,并且是不可变的。
  • 使用CharSequence,您不知道具体实现的特定功能可能是什么。

The CharSequenceobject might represent an enormous chunk of text, and therefore has memory implications. Or may be many chunks of text tracked separately that will need to be stitched together when you call toString, and therefore has performance issues. The implementation may even be retrieving text from a remote service, and therefore has latency implications.

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

and converting from one to another?

并从一种转换为另一种?

You generally won't be converting back and forth. A Stringisa CharSequence. If your method declares that it takes a CharSequence, the calling programmer may pass a Stringobject, or may pass something else such as a StringBufferor StringBuilder. Your method's code will simply use whatever is passed, calling any of the CharSequencemethods.

您通常不会来回转换。AString一个CharSequence。如果您的方法声明它需要 a CharSequence,则调用程序员可能会传递一个String对象,或者可能会传递其他内容,例如 aStringBufferStringBuilder。您方法的代码将简单地使用传递的任何内容,调用任何CharSequence方法。

The closest you would get to converting is if your code receives a CharSequenceand you know you need a String. Perhaps your are interfacing with old code written to Stringclass rather than written to the CharSequenceinterface. Or perhaps your code will work intensively with the text, such as looping repeatedly or otherwise analyzing. In that case, you want to take any possible performance hit only once, so you call toStringup front. Then proceed with your work using what you know to be a single piece of text entirely in memory.

最接近转换的是,如果您的代码收到一个CharSequence并且您知道您需要一个String. 也许您正在与写入String类而不是写入接口的旧代码CharSequence交互。或者,您的代码可能会大量处理文本,例如重复循环或以其他方式进行分析。在这种情况下,您只想对任何可能的性能造成影响,因此您需要toString提前调用。然后使用您所知道的完全在内存中的一段文本继续您的工作。

Twisted history

扭曲的历史

Note the comments made on the accepted Answer. The CharSequenceinterface was retrofitted onto existing class structures, so there are some important subtleties (equals()& hashCode()). Notice the various versions of Java (1, 2, 4 & 5) tagged on the classes/interfaces—quite a bit of churn over the years. Ideally CharSequencewould have been in place from the beginning, but such is life.

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

My class diagram below may help you see the big picture of string types in Java 7/8. I'm not sure if all of these are present in Android, but the overall context may still prove useful to you.

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

diagram of various string-related classes and interfaces

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

回答by Srinivas Thammanaboina

CharSequence is a readable sequence of char values which implements String. it has 4 methods

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

  1. charAt(int index)
  2. length()
  3. subSequence(int start, int end)
  4. toString()
  1. charAt(int 索引)
  2. 长度()
  3. 子序列(int 开始,int 结束)
  4. toString()

Please refer documentation CharSequence documentation

请参考文档CharSequence 文档

回答by Xiaogang

CharSequenceis an interface and Stringimplements it. You can instantiate a Stringbut you could not do that for CharSequencesince it is an interface. You can find other implementations in CharSequencein the official Java website.

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

回答by Suragch

CharSequence

字符序列

A CharSequenceis an interface, not an actual class. An interface is just a set of rules (methods) that a class must contain if it implements the interface. In Android a CharSequenceis an umbrella for various types of text strings. Here are some of the common ones:

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

(You can read more about the differences between these here.)

(您可以在此处阅读有关这些差异的更多信息。)

If you have a CharSequenceobject, then it is actually an object of one of the classes that implement CharSequence. For example:

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

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

The benefit of having a general umbrella type like CharSequenceis that you can handle multiple types with a single method. For example, if I have a method that takes a CharSequenceas a parameter, I could pass in a Stringor a SpannableStringBuilderand it would handle either one.

拥有通用伞型类型的好处CharSequence是您可以使用单个方法处理多种类型。例如,如果我有一个将 aCharSequence作为参数的方法,我可以传入 aString或 aSpannableStringBuilder并且它会处理任何一个。

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

String

细绳

You could say that a Stringis just one kind of CharSequence. However, unlike CharSequence, it is an actual class, so you can make objects from it. So you could do this:

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

String myString = new String();

but you can't do this:

但你不能这样做:

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

Since CharSequenceis just a list of rules that Stringconforms to, you could do this:

由于CharSequence只是String符合规则的列表,您可以这样做:

CharSequence myString = new String();

That means that any time a method asks for a CharSequence, it is fine to give it a String.

这意味着任何时候一个方法要求 a CharSequence,就可以给它 a String

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

// ...

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

However, the opposite is not true. If the method takes a Stringparameter, you can't pass it something that is only generally known to be a CharSequence, because it might actually be a SpannableStringor some other kind of CharSequence.

然而,事实并非如此。如果该方法接受一个String参数,则不能向它传递通常只知道是 a 的东西CharSequence,因为它实际上可能是 aSpannableString或其他类型的CharSequence

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

// ...

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