在Android中编程,大多数文本值都在CharSequence中。
为什么呢?使用CharSequence而不是String的好处是什么,主要影响是什么?
在使用它们和从一种转换到另一种时,主要的区别是什么,预期会出现什么问题?
在Android中编程,大多数文本值都在CharSequence中。
为什么呢?使用CharSequence而不是String的好处是什么,主要影响是什么?
在使用它们和从一种转换到另一种时,主要的区别是什么,预期会出现什么问题?
当前回答
CharSequence进行
CharSequence是一个接口,而不是实际的类。接口只是类实现接口时必须包含的一组规则(方法)。在Android中,CharSequence是各种类型文本字符串的保护伞。以下是一些常见的错误:
字符串(没有样式跨度的不可变文本) StringBuilder(没有样式跨度的可变文本) SpannableString(具有样式跨度的不可变文本) SpannableStringBuilder(具有样式跨度的可变文本)
(你可以在这里阅读更多关于它们之间的区别。)
如果你有一个CharSequence对象,那么它实际上是一个实现CharSequence的类的对象。例如:
CharSequence myString = "hello";
CharSequence mySpannableStringBuilder = new SpannableStringBuilder();
使用CharSequence这样的通用伞形类型的好处是,您可以用一个方法处理多个类型。例如,如果我有一个方法,以CharSequence作为参数,我可以传入String或SpannableStringBuilder,它将处理任何一个。
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();
}
其他回答
字符串是CharSequences,所以你可以只使用字符串,不用担心。Android只是试图通过允许你指定其他CharSequence对象来提供帮助,比如stringbuffer。
在实际的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进行
CharSequence是一个接口,而不是实际的类。接口只是类实现接口时必须包含的一组规则(方法)。在Android中,CharSequence是各种类型文本字符串的保护伞。以下是一些常见的错误:
字符串(没有样式跨度的不可变文本) StringBuilder(没有样式跨度的可变文本) SpannableString(具有样式跨度的不可变文本) SpannableStringBuilder(具有样式跨度的可变文本)
(你可以在这里阅读更多关于它们之间的区别。)
如果你有一个CharSequence对象,那么它实际上是一个实现CharSequence的类的对象。例如:
CharSequence myString = "hello";
CharSequence mySpannableStringBuilder = new SpannableStringBuilder();
使用CharSequence这样的通用伞形类型的好处是,您可以用一个方法处理多个类型。例如,如果我有一个方法,以CharSequence作为参数,我可以传入String或SpannableStringBuilder,它将处理任何一个。
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();
}
一般来说,使用接口允许您以最小的附带损害改变实现。虽然java.lang.String非常流行,但在某些情况下,人们可能想使用另一种实现。通过围绕CharSequences而不是string构建API,代码提供了这样做的机会。
CharSequence =接口字符串=具体实现
CharSequence是一个接口。 有几个类实现了这个接口。 String就是这样一个类,是CharSequence的具体实现。
你说:
从一个转换到另一个
没有从字符串进行转换。
每个String对象都是一个CharSequence。 每个CharSequence都可以生成一个String。叫CharSequence进行::toString。如果CharSequence恰好是String,则该方法返回对自己对象的引用。
换句话说,每个字符串都是CharSequence,但并不是每个CharSequence都是String。
编程到接口
在Android中编程,大多数文本值都在CharSequence中。 为什么呢?使用CharSequence而不是String的好处是什么,主要影响是什么?
通常,面向接口编程比面向具体类编程更好。这产生了灵活性,因此我们可以在特定接口的具体实现之间切换,而不会破坏其他代码。
在开发供各种程序员在各种情况下使用的API时,编写代码时尽可能提供和采用最通用的接口。这使得调用程序可以自由地使用该接口的各种实现,无论哪种实现最适合其特定上下文。
例如,看看Java集合框架。如果你的API给出或接受一个有序的对象集合,将你的方法声明为使用List,而不是ArrayList, LinkedList或任何其他第三方的List实现。
当编写一个快速而肮脏的小方法只供您的代码在一个特定的地方使用时,而不是编写一个API用于多个地方时,您不需要使用更通用的接口而不是特定的具体类。但即便如此,使用最通用的界面也会造成伤害。
在使用它们时,主要的区别是什么,预期会出现什么问题,
对于String,你知道你有一个单独的文本,完全在内存中,并且是不可变的。 使用CharSequence,您不知道具体实现的特定特性可能是什么。
CharSequence对象可能表示一个巨大的文本块,因此有内存影响。或者可能有许多单独跟踪的文本块,在调用toString时需要将它们拼接在一起,因此存在性能问题。实现甚至可能从远程服务检索文本,因此存在延迟问题。
从一个转换到另一个?
你通常不会来回转换。字符串是一个CharSequence。如果你的方法声明它接受一个CharSequence,调用它的程序员可能会传递一个String对象,或者传递其他东西,比如StringBuffer或StringBuilder。您的方法代码将简单地使用所传递的任何东西,调用任何CharSequence方法。
The closest you would get to converting is if your code receives a CharSequence and you know you need a String. Perhaps your are interfacing with old code written to String class rather than written to the CharSequence interface. 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 toString up front. Then proceed with your work using what you know to be a single piece of text entirely in memory.
扭曲的历史
注意对已接受的答案所作的评论。CharSequence接口被改造到现有的类结构上,因此有一些重要的微妙之处(equals() & hashCode())。请注意标记在类/接口上的各种Java版本(1、2、4和5)——这些年来变化很大。理想情况下CharSequence应该从一开始就存在,但这就是生活。
下面的类图可以帮助您了解Java 7/8中字符串类型的总体情况。我不确定是否所有这些都存在于Android中,但总体上下文可能仍然对你有用。