为什么String.indexOf不使用异常但在找不到子字符串时返回-1?

时间:2009-05-13 18:11:12

标签: java exception-handling

为什么String.indexOf不使用异常但在找不到子字符串时返回-1?

这个问题的目的是:当我们开始自定义异常时。

我相信避免需要返回特殊错误代码是正确的设计路径。

你有什么看法?

10 个答案:

答案 0 :(得分:29)

根据经验,如果方法的目的是检查某些东西,那么缺少某些东西不应该是一个例外。如果方法假设某些事情是真的,那么缺少那个东西将是一个例外。因此“File.exists()”不会抛出FileNotFoundException,但“File.open()”会抛出。

答案 1 :(得分:18)

异常是针对特殊情况,当字符串不包含字母时,这几乎不例外,除非您在某些极端情况下使用它。如果这就是你正在做的事情,你总是可以选择抛出自己的例外。

答案 2 :(得分:16)

最后我听到的是......

  

'当你的时候抛出异常   方法无法做到它   承诺' - Jeff Richter CVC第二版

  • IndexOf()承诺返回第一次出现的char / string的索引。如果由于某种原因无法完成工作,它会引发异常。它完成了它的工作,但没有找到字符串,因此返回-1来传达未找到的结果。
  • File.Open()将为不存在的文件路径抛出FileNotException,因为它无法执行它所承诺的内容。即打开指定的文件。

答案 3 :(得分:6)

返回-1几乎和抛出异常一样可怕。正确的方法是使用选项类型,如果语言更好地支持它。在有结果的正常情况下,将结果包装在对象中并返回。否则,您将返回表示“未结果”情况的对象。

在通话网站中,你必须检查它是哪一个;你不能仅仅因为它们的超类型而使用返回值,它们必须通过模式匹配进行检查。

伪语法:

class Option[a] = Some[a] | None,

其中a是泛型类型参数,Some表示带有值的结果,None表示没有值的非结果。

在indexOf的情况下,您将拥有:

Option[Integer] indexOf(char c) = {
   if(found) return Some(index)
   else return None
}

你用这种方式:

result = "uncle".indexOf('c')
result match {
  Some(i) => System.out.println("index was: " + i);
  None => System.out.println("no value");
}

如果你从匹配中省略了Some或None(这是一种通用的开关),编译器会给你一个警告。

答案 4 :(得分:3)

处理检查-1比处理异常要容易得多。

答案 5 :(得分:3)

另外,因为例外情况在性能方面很昂贵

答案 6 :(得分:3)

除了一般反对异常的参数之外,我还要补充一点,-1可以是indexOf和lastIndexOf的有用结果,而不仅仅是一个特殊值。例如,要从可能包含或不包含路径的字符串中解析文件名:

String filename = arg.substring(arg.lastIndexOf('/') + 1);

虽然可能是一个人为的例子,但除了例外情况,这会更麻烦。

答案 7 :(得分:2)

这里有很多好的答案。这是一个设计问题,其中实用主义优先于遵循“规则”。在这种情况下,存在一些相互矛盾的“规则”:

  • 避免使用特殊值作为返回数据(不是自我记录,要求开发人员以与其他代码不同的方式处理特殊值)

VS

  • 在代码的例行执行期间不会抛出异常,只有在出现意外情况时

我同意这个设计决定。但是,如果不这样做,则可以在检查索引之前始终编写自己的代码以检查字符串是否存在。不要成为你语言的囚犯,根据自己的意愿行事。语言本应受到折磨!

答案 8 :(得分:1)

我认为当发生意外时,必须抛出异常。 也就是说,String中找不到的子字符串不是意料之外的,可能会发生,这是一个合理的结果。

我同意你应该尽量避免返回错误代码,但在这种情况下我们只有两个选择,找到字符串或找不到字符串。

答案 9 :(得分:0)

直到Java的作者string.indexOf告诉我们实际历史......

假设我们必须从头开始设计它,这个问题有一些明显的设计约束:

  1. indexOf必须返回一个数值,以便在找到匹配项时知道它在哪里
  2. 保证有效索引始终为整数
  3. 数组(和字符串)索引在Java中基于零
  4. Java是强类型的
  5. 整数数字类型用Java签名
  6. 鉴于这些基本约束,函数返回类型的一些可能选择是整数(理想情况下是一个足以表示最大可能字符串中最后一个索引的类型),或者...... Object(也许返回null表示未找到)。但实际上,返回Object既不高效也不方便用户,因为需要检查其有效性并在使用之前投射到找到的案例 - 所以它不是真正可行的选择!

    所以让我们用一个整数。如果找不到,我们是否要抛出异常?抛出异常有其自身的多个问题 - 创建异常对象并跳转到异常处理程序可能效率很低,并且围绕indexOf调用编写try / catch块也不好玩!

    所以,让我们说我们缩小了它:它必须返回(签名)整数类型,而抛出异常。现在应返回哪个整数值表示未找到?

    为了允许在尽可能大的字符串中进行搜索,我们应该保留所有正整数以用于成功找到的含义。相反,不需要任何负数来代表发现的数字。索引,因此所有可能都可用作表示“未找到”的返回代码。

    如果我们可以选择任何负数,代表未找到,或只是说'所有负回报值意味着找不到'它会做的...但它会是最好的设计吗?

    使用-1代替其他负数的原因是什么?我最喜欢的原因是简单的#-1; -1很容易让每个人都记住,你可以对它进行精确的平等测试'。 (而不是被迫使用不平等,并考虑一个一个一个的问题,比如你是想要低于或低于或等于,以及与之比较的值,零或负值)

    我有时也很佩服Chris的理由(释义)'它与substring(foundIndex + 1)'很好地合作。