简体   繁体   English

何时在API中使用CharSequence

[英]When to use CharSequence in an API

I'm designing a public interface (API) for a package. 我正在为包设计一个公共接口(API)。 I wonder, should I use CharSequence generally instead of String . 我想知道,我应该使用CharSequence而不是String (I'm mainly talking about the public interfaces). (我主要谈的是公共接口)。

Are there any drawbacks of doing so? 这样做有什么缺点吗? Is it considered a good practice? 这被认为是一种好习惯吗?

What about using it for identifier-like purposes (when the value is matched against a set in a hash-based container)? 如何将它用于类似标识符的目的(当值与基于散列的容器中的集合匹配时)?

CharSequence is rarely used in general purpose libraries. CharSequence很少用于通用库。 It should usually be used when your main use case is string handling (manipulation, parsing, ...). 当你的主要用例是字符串处理(操作,解析,......)时,通常应该使用它。

Generally speaking you can do anything with a CharSequence that you could do with a String (trivially, since you can convert every CharSequence into a String ). 一般来说,你可以使用CharSequence做任何事情,你可以使用String (通常,因为你可以将每个CharSequence转换为一个String )。 But there's one important difference: A CharSequence is not guaranteed to be immutable! 但是有一个重要的区别: CharSequence不能保证不变! Whenever you handle a String and inspect it at two different points in time, you can be sure that it will have the same value every time. 无论何时处理String并在两个不同的时间点检查它,您都可以确保它每次都具有相同的值。

But for a CharSequence that's not necessarily true. 但对于CharSequence ,这不一定是真的。 For example someone could pass a StringBuilder into your method and modify it while you do something with it , which can break a lot of sane code. 例如,有人可以将StringBuilder传递给您的方法,并在您使用它时对其进行修改,这可能会破坏很多合理的代码。

Consider this pseudo-code: 考虑这个伪代码:

public Object frobnicate(CharSequence something) {
  Object o = getFromCache(something);
  if (o == null) {
    o = computeValue(something);
    putIntoCache(o, something);
  }
  return o;
}

This looks harmless enough and if you'd had used String here it would mostly work (except maybe that the value might be calculated twice). 这看起来很无害,如果你在这里使用了String ,那么它几乎可以工作(除非可能会计算两次值)。 But if something is a CharSequence then its content could change between the getFromCache call and the computeValue call. 但是如果somethingCharSequence那么它的内容可能会在getFromCache调用和computeValue调用之间发生变化。 Or worse: between the computeValue call and the putIntoCache call! 或者更糟:在computeValue调用和putIntoCache调用之间!

Therefore: only accept CharSequence if there are big advantages and you know the drawbacks . 因此: 只有接受CharSequence如果有很大的优势 ,你知道缺点

If you accept CharSequence you should document how your API handles mutable CharSequence objects. 如果接受CharSequence ,则应记录API如何处理可变的CharSequence对象。 For example: "Modifying an argument while the method executes results in undefined behaviour." 例如:“在方法执行时修改参数会导致未定义的行为。”

This does depend on what you need, I'd like to state two advantages of String , however. 这取决于你需要什么,我想说明String两个优点。

From CharSequence 's documentation : 来自CharSequence的文档

Each object may be implemented by a different class, and there is no guarantee that each class will be capable of testing its instances for equality with those of the other. 每个对象可以由不同的类实现,并且不能保证每个类能够测试其实例与另一个的实例是否相等。 It is therefore inappropriate to use arbitrary CharSequence instances as elements in a set or as keys in a map. 因此,将任意CharSequence实例用作集合中的元素或映射中的键是不合适的。

Thus, whenever you need a Map or reliable equals / hashCode , you need to copy instances into a String (or whatever). 因此,无论何时需要Map或可靠的equals / hashCode ,都需要将实例复制到String (或其他)中。

Moreover, I think CharSequence does not explicitly mention that implementations must be immutable. 此外,我认为CharSequence没有明确提到实现必须是不可变的。 You may need to do defensive copying which may slow down your implementations. 您可能需要进行防御性复制 ,这可能会降低您的实施速度。

Java CharSequence is an interface. Java CharSequence是一个接口。 As the API says, CharSequence has been implemented in CharBuffer , Segment , String , StringBuffer , StringBuilder classes. 正如API所说, CharSequence已经在CharBufferSegmentStringStringBufferStringBuilder类中实现。 So if you want to access or accept your API from all these classes then CharSequence is your choice. 因此,如果您想要从所有这些类访问或接受您的API,那么CharSequence是您的选择。 If not then String is very good for a public API because it is very easy & everybody knows about it. 如果没有那么String对于公共API非常好,因为它很容易并且每个人都知道它。 Remember CharSequence only gives you 4 method, so if you are accepting a CharSequence object through a method, then your input manipulation ability will be limited. 记住CharSequence只给你4个方法,所以如果你通过一个方法接受一个CharSequence对象,那么你的输入操作能力将受到限制。

If a parameter is conceptually a sequence of chars, use CharSequence. 如果参数在概念上是一系列字符,请使用CharSequence。

A string is technically a sequence of chars, but most often we don't think of it like that; 字符串在技术上是一系列字符,但大多数情况下我们并不这么认为; a string is more atomic / holistic, we don't usually care about individual chars. 一个字符串更原子/整体,我们通常不关心个别字符。

Think about int - though an int is technically a sequence of bits, we don't usually care about individual bits. 想想int - 虽然int在技术上是一个位序列,但我们通常不关心单个位。 We manipulate ints as atomic things. 我们将int作为原子事物来操纵。

So if the main work you are going to do on a parameter is to iterate through its chars, use CharSequence. 因此,如果您要对参数执行的主要工作是迭代其字符,请使用CharSequence。 If you are going to manipulate the parameter as an atomic thing, use String. 如果要将参数作为原子操作,请使用String。

You can implement CharSequence to hold your passwords, because the usage of String is discouraged for that purpose. 您可以实现CharSequence来保存密码,因为不鼓励使用String The implementation should have a dispose method that wipes out the plain text data. 实现应该有一个dispose方法来清除纯文本数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM