【问题标题】:How should substring() work?substring() 应该如何工作?
【发布时间】:2010-10-27 09:16:02
【问题描述】:

我不明白为什么 Java 的 [String.substring() 方法](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html#substring(int,%20int%29) 是这样指定的。我不能告诉它从编号位置开始并返回指定数量的字符;我必须自己计算结束位置。如果我指定超出字符串末尾的结束位置,而不是只为我返回字符串的其余部分,Java 会抛出异常。

我习惯于 substring()(或 substr())采用两个参数的语言:起始位置和长度。这在客观上是否比 Java 做的更好,如果是,你能证明吗?您所见过的 substring() 的最佳语言规范是什么?什么时候让一种语言以不同的方式做事是个好主意? Java 抛出的 IndexOutOfBoundsException 是不是一个好的设计理念?这一切都归结为个人喜好吗?

【问题讨论】:

  • 这确实是个人喜好问题,这就是使这个“主观和争论”的原因。我在不同时间需要子字符串的“长度”和“结束位置”两种风格,所以对我来说,说一个比另一个“更好”是没有意义的。
  • 没有必要仅仅因为它是主观的而争论。嘘。我们不能在没有圣战的情况下讨论语言决策的相对优点吗?如果 Jon Skeet 认为值得回复并且不仅仅是呼吁争论,那肯定意味着什么吗?
  • 如果我编辑它以去掉“惊讶”和“不便”这两个词,它会显得不那么有争议,因为实际上没有人争论吗?语言设计问题(在大多数情况下本质上涉及一些主观权衡)是否不适合 Stack Overflow?

标签: language-agnostic language-design substring substr


【解决方案1】:

有时第二个参数是长度更方便,有时第二个参数是“停止前的偏移量”更方便。同样,有时“如果我给你的东西太大,就到字符串的末尾”很方便,有时它表示一个错误,应该真的抛出一个异常。

如果您有固定长度的字段,则第二个参数是长度很有用。例如:

// C#
String guid = fullString.Substring(offset, 36);

第二个参数是一个偏移量,如果你要上到另一个分隔符,它会很有用:

// Java
int nextColon = fullString.indexOf(':', start);
if (start == -1)
{
    // Handle error
}
else
{
    String value = fullString.substring(start, nextColon);
}

根据我的经验,通常情况下,您要使用的与您当前平台上提供的相反:)

【讨论】:

    【解决方案2】:

    我习惯了 substring()(或 substr())需要两个 参数:一个起始位置和一个 长度。这客观上更好吗 比Java的方式,如果是这样, 你能证明吗?

    不,客观上并没有更好。这完全取决于您要使用它的上下文。如果你想提取一个特定长度的子字符串,那就不好了,但是如果你想提取一个以第一次出现“。”结尾的子字符串。在字符串中,这比您首先必须计算长度要好。问题是:哪个要求更常见?我会说后者。当然,最好的解决方案是在 API 中同时拥有这两个版本,但如果您一直需要基于长度的版本,那么使用静态实用程序方法并不是那么可怕。

    至于例外,是的,这绝对是个好设计。您要求特定的东西,而当您无法获得特定的东西时,API 不应尝试猜测您可能想要的东西 - 这样,错误会更快地显现出来。

    此外,Java 确实有一个 alternative substring() 方法,它返回从开始索引到字符串结尾的子字符串。

    【讨论】:

      【解决方案3】:

      第二个参数应该是可选的,第一个参数应该接受负值..

      【讨论】:

        【解决方案4】:

        如果您leave off the 2nd parameter,它将为您转到字符串的末尾,而无需您计算它。

        【讨论】:

        • 有时您希望从 x 到 20 个字符后或字符串末尾,以较短者为准。
        • 有时您需要从 x 到字符串其余部分的一半,不包括数字。没有任何 API 可以满足所有可能的要求。
        • 没有 API 可以满足所有可能的要求,但我认为某些 API 可能比其他 API 明显满足更多的要求。我仍在思考这个问题,并观察反应。 :)
        【解决方案5】:

        得到一些反馈后,我发现第二个参数作为索引方案何时有用,但到目前为止,所有这些方案似乎都在解决其他语言/API 限制。例如,API 没有提供方便的例程来给我输入字符串中第一个冒号前后的字符串,因此我获取该字符串的索引并调用 substring()。 (这就解释了为什么 substr() 中的第二个位置参数超过了所需的索引 1,IMO。)

        在我看来,随着语言工具包中的一组更全面的字符串处理功能,第二个参数作为索引的场景输给了第二个参数作为长度。但是有人请给我一个反例。 :)

        【讨论】:

        • "例如,API 没有提供方便的例程来给我输入字符串中第一个冒号前后的字符串,因此我获取该字符串的索引并调用 substring()。 " - 如果您想要一个 API 来做所有事情,我们将有大量的 API 来学习,而 Stack Overflow 将包含一些答案,询问为什么有人没有在 String 对象上使用 30000 种方法中的一种,而不是花 30 秒自己编写它。这就是为什么我们是程序员,因为还没有写完所有东西。如果您需要大量执行任务 X,请编写自己的库来完成。
        • 为什么每个人都想编写自己的库,因为他们可以通过一个实现来调试所有相关的栅栏错误?
        【解决方案6】:

        如果你把它收起来,这个问题应该不会再困扰你的梦想,你最终会睡个好觉:

        public String skipsSubstring(String s, int index, int length) {
            return s.subString(index, index+length);
        }
        

        【讨论】:

        • 这只会引发 IndexOutOfBoundsException。 :) 我需要添加一个检查以使 substring() 的第二个参数为 min(index + length, s.length())。
        • 看过 String 的实现,Java 提供这两种范式似乎并不难:substring() 可以继续,substr() 可以遵循更常见的语义在其他语言中。在内部,实现似乎很简单。
        • 我认为同时拥有具有不同语义的 substring() 和 substr() 会很糟糕。我几乎可以保证有一半以上的时间我会使用错误的软件——而且我想我的大多数程序员同事也会这样做。
        • 也许如果名字能更好的区分,那么呢?
        • >> 这只会引发 IndexOutOfBoundsException。 :) 我需要添加一个检查以使 substring() 的第二个参数为 min(index + length, s.length())。----是的,当你抓住它时,一定要抛出一个IndexOutOfBoundsException - 不要默默地失败或猜测,这是可怕的设计。尽早失败并努力失败。
        猜你喜欢
        • 2016-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-16
        • 2015-03-31
        相关资源
        最近更新 更多