问题
Why String.indexOf do not use exception but return -1 when substring not found?
The purpose of this question is: when we start custom exception.
I believe avoid the need to return special error code is right design path.
What's your opinion?
回答1:
As a rule of thumb, if the purpose of a method is to check for something, then the lack of that something shouldn't be an exception. If the method is assuming that something is true, then the absence of that something would be an exception. Thus "File.exists()" doesn't throw a FileNotFoundException, but "File.open()" does.
回答2:
exceptions are for exceptional cases, when a string does not contain a letter, that's hardly exceptional, unless you are using it for some extreme case. If that's what you are doing, you can always choose to throw your own exception.
回答3:
Last I heard on that was...
'You throw an exception when your method is unable to do what it promises to' - Jeff Richter CVC 2nd ed
- IndexOf() promises you to return the index of the first occurrence of a char/string. It would have thrown an exception if it was unable to do its job for some reason. It did its job but didn't find the string and hence returns -1 to convey the not-found result.
- File.Open() will throw a FileNotException for a non-existing filepath since it is unable to do what it promises .. i.e. open the specified file.
回答4:
returning -1 is almost as horrible as throwing an exception. The correct way would be to use option type if language just supported it better. In normal situation where there is result, you wrap the result in object and return that. Otherwise you return an object representing the "not result" situation.
In call site you have to check which one was it; you can't just use the return value because of their super type, they have to be inspected via pattern matching.
In pseudo syntax:
class Option[a] = Some[a] | None,
where a is generic type parameter, Some represents a result with value and None non-result without value.
in indexOf case you would have:
Option[Integer] indexOf(char c) = {
if(found) return Some(index)
else return None
}
and you use that this way:
result = "uncle".indexOf('c')
result match {
Some(i) => System.out.println("index was: " + i);
None => System.out.println("no value");
}
If you omitted either Some or None from matching (which is kinda generalized switch), compiler would give you a warning.
回答5:
Also because exceptions are expensive in terms of performance
回答6:
It's a lot easier to deal with checking for a -1 than catching an exception.
回答7:
Aside from the arguments against exceptions in general, I would add that -1 can be a useful result from indexOf and lastIndexOf, not just a special value. For instance, to parse the filename from a string that may or may not contain a path:
String filename = arg.substring(arg.lastIndexOf('/') + 1);
While perhaps a contrived example, this would be a bit more cumbersome with exceptions.
回答8:
Lots of good answers here. This is a design issue where pragmatism has taken precedence over following "rules". In this case, there are some conflicting "rules":
- avoid using special values as return data (not self-documenting, requires developer to handle special value in a distinct way from other code)
vs.
- don't throw exceptions during routine execution of code, only when something unexpected happens
I agree with this design decision. If you do not, however, you can always write your own code to check for the existence of a string before checking its index. Do not be a prisoner of your language, bend it to your will. Languages are meant to be tortured!
回答9:
I think that one has to throw an exception when something unexpected happens. That said, a substring not found in a String is not that unexpected, can happen, it is a reasonable result.
I agree with you that one should try to avoid returning error codes, but in this case we have only two choices, string found or string not found.
回答10:
Until the author of Java's string.indexOf
tells us the actual history...
Let's suppose we had to design it from scratch, some obvious design constraints for this problem:
indexOf
must return a numeric value, so that when a match is found, you know where it is- valid indexes are guaranteed to be always integers
- array (and string) indexes are zero-based in Java
- Java is strongly typed
- the integer numeric types are signed in Java
Given those basic constraints, some possible choices for function return type the would be integer (ideally of a type large enough to represent the last index in the largest possible string), OR... Object
(and perhaps return null to indicate not found). But in practice returning Object
would be neither efficient nor user-friendly, due to the need to check its validity and cast before usage for the found case - so it's not really a viable option!
So let's go with an integer. Do we want to throw an exception if not found? Throwing exceptions has multiple problems of its own - creating exception objects and jumping to exception handlers can be quite inefficient, and writing try/catch blocks around indexOf
calls is no fun either!
So let's say we've narrowed it down: it has to return a (signed) integer type, and not throw an exception. Now which integer value should it return to represent not found?
In order to allow searching in strings as large as possible, we should reserve all positive integers for usage as meaning successfully found. Conversely, none of the negative numbers is needed to represent a 'found' index, so all are potentially available to use as return codes representing 'not found'.
If we could have picked any negative number, to represent not found, or just said 'all negative return values mean not found' it would do the job... But would it be the best design?
What are some reasons to use -1 instead of other negative numbers? My favorite reasons are simply '-1 is easy for everyone to remember, and you can do exact equality tests on it'. (Instead of being forced to use inequalities and think about off-by-one problems like whether you want less-than or less-than-or-equal, and what value to compare with, zero or negative one)
I also sometimes admire Chris's reason that (paraphrasing) 'it works nicely with substring(foundIndex + 1)
'.
来源:https://stackoverflow.com/questions/859494/why-string-indexof-do-not-use-exception-but-return-1-when-substring-not-found