何时在API中使用CharSequence

vbe*_*nce 22 java charsequence

我正在为包设计一个公共接口(API).我想知道,我应该CharSequence普遍使用而不是String.(我主要谈的是公共接口).

这样做有什么缺点吗?这被认为是一种好习惯吗?

如何将它用于类似标识符的目的(当值与基于散列的容器中的集合匹配时)?

Joa*_*uer 31

CharSequence很少用于通用库.当你的主要用例是字符串处理(操作,解析,......)时,通常应该使用它.

一般来说,你可以做CharSequence一些你可以用a 做的事情(通常String,因为你可以将每个转换CharSequence为aString).但是有一个重要的区别:A CharSequence不能保证不变!无论何时处理String并在两个不同的时间点检查它,您都可以确保它每次都具有相同的值.

但对于一个CharSequence不一定是真的.例如,有人可以将一个StringBuilder方法传递给你的方法,并在你做一些事情时修改,这可能会打破很多合理的代码.

考虑这个伪代码:

public Object frobnicate(CharSequence something) {
  Object o = getFromCache(something);
  if (o == null) {
    o = computeValue(something);
    putIntoCache(o, something);
  }
  return o;
}
Run Code Online (Sandbox Code Playgroud)

这看起来很无害,如果你已经在String这里使用过,它大部分都会起作用(除非可能会计算两次这个值).但如果something是,CharSequence则其内容可能会在getFromCache通话和computeValue通话之间发生变化.或者更糟糕的是:在computeValue通话和putIntoCache通话之间!

因此:只有CharSequence在有很大优势并且了解其缺点的情况下才能接受.

如果您接受CharSequence,则应记录您的API如何处理可变CharSequence对象.例如:"在方法执行时修改参数会导致未定义的行为."

  • @MarkPeters:是的,这通常是正确的.*big*的区别在于,对于`String`来说,它永远不会改变的假设是非常硬编码到每个Java开发人员大脑中(而大多数人认为`List`是可变的).因此,当从`String`切换到`CharSequence`时,他们可能会错过`CharSequence`不一定与`String`共享那个不错的属性的事实. (5认同)
  • 我会说CharSequence over String的另一个主要用例是"大"字符序列,因为CharSequence impl可能会同时处理并非全部在内存中的数据. (5认同)
  • *例如,有人可以将 StringBuilder 传递到您的方法中,并在您用它做某事时对其进行修改* 难道这不能用于许多类,尤其是“List”?我的库代码是否应该只接受“ImmutableList”?是的,有人可以在您的方法正在处理时更改列表,但他们会愚蠢。如果它冒着你的不变量的风险,那么在验证输入之前做一个防御性的副本。 (2认同)
  • @jtahlborn:更准确地说,我的意思是"字符串处理",例如,如果你输出或附加到某个日志文件,那么接受`CharSequence`可能是有用的(例如,能够记录`StringBuilder`).解析器是另一个应该接受`CharSequence`的例子:它不需要内存中的所有内容,它只需要能够迭代每个字符. (2认同)

Mat*_*eid 6

这取决于你需要什么,但我想说明两个优点String.

来自CharSequence的文件:

每个对象可以由不同的类实现,并且不能保证每个类能够测试其实例与另一个的实例是否相等.因此,将任意CharSequence实例用作集合中的元素或映射中的键是不合适的.

因此,无论何时需要Map或者需要equals/ hashCode,都需要将实例复制到String(或其他)中.

而且,我认为CharSequence没有明确提到实现必须是不可变的.您可能需要进行防御性复制,这可能会降低您的实施速度.


Saj*_*sad 5

Java CharSequence是一个接口.由于API称,CharSequence已得到落实CharBuffer,Segment,String,StringBuffer,StringBuilder类.因此,如果您想要从所有这些类访问或接受您的API,那么CharSequence您可以选择.如果没有,那么String对于公共API非常有用,因为它很容易并且每个人都知道它.记住CharSequence只给你4个方法,所以如果你CharSequence通过一个方法接受一个对象,那么你的输入操作能力将受到限制.

  • @AndrzejDoyle:`toString()`对于特定的实现来说可能真的很贵.大多数实现需要将整个字符序列复制到新数组中.如果您的第一步是从`CharSequence`获取`String`,那么您将以隐藏性能命中为代价提供灵活性.其中没有多少价值,也可以采用"String"并让用户进行转换,以便他们充分了解惩罚. (5认同)