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

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

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

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

你怎么看?

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

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

最后我听到的是……

“当你的方法无法做到它所承诺的时候,你会抛出exception” – Jeff Richter CVC第二版

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

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

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

在伪语法中:

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

其中a是generics类型参数,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(这是一种通用的开关),编译器会给你一个警告。

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

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

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

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

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

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

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

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

我同意这个设计决定。 但是,如果不这样做,则可以在检查索引之前始终编写自己的代码以检查字符串是否存在。 不要成为你的语言的囚犯,屈服于你的意志。 语言意味着折磨!

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

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

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

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

  1. indexOf必须返回一个数值,以便在找到匹配项时知道它在哪里
  2. 有效索引保证总是整数
  3. 数组(和字符串)索引在Java中从零开始
  4. Java是强类型的
  5. 整数数字类型在Java中签名

给定这些基本约束,函数返回类型的一些可能选择是整数(理想情况下是足以表示最大可能字符串中的最后一个索引的类型),OR … Object (并且可能返回null以指示未找到) 。 但实际上返回Object既不高效也不方便用户,因为需要检查其有效性并在使用之前进行铸造 – 因此它不是真正可行的选择!

那么我们来看一个整数。 如果找不到,我们是否要抛出exception? 抛出exception有其自身的多个问题 – 创建exception对象并跳转到exception处理程序可能效率很低,并且在indexOf调用周围编写try / catch块也不好玩!

所以我们说我们已经缩小了它:它必须返回一个(带符号)整数类型,而不是抛出exception。 现在应返回哪个整数值表示未找到?

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

如果我们可以选择任何负数,代表未找到,或只是说“所有负面回报值意味着没有找到”它就能完成这项工作……但它会是最好的设计吗?

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

我有时也很欣赏克里斯的理由(释义)’它与substring(foundIndex + 1) ‘很好地配合。