[英]Java : Proper way a method() should handle a bad call
我经常面对这个问题。 让我们看一个简单的例子,我得到了这个简单的方法:它在String[]
检索String
的位置。
public int getStringPosition(String s, String[] text) {
for (int i = 0; i < text.length; i++) {
if (text[i].equals(s)) {
return i;
}
}
return text.length;
}
但是如果String不在数组中呢? 这里,它返回数组的大小(一个int
,它不能正常使用该方法)。 它也可以返回-1
。 我希望它会返回null,但这似乎不可能。
无论如何,这个方法将通过其他一些方法在同一个类中使用。 我的问题非常笼统, 如何处理无法返回预期的情况?
如果s
不在text
情况不是调用方法的有效方法,则应抛出异常,例如IllegalParameterException。
但是如果以这种方式调用方法是可以的,则不应该抛出异常,因为它是有效的预期用法。 在这种情况下,您可以返回-1
。
但是-1
在这种情况下是一个“幻数”,这是一种不好的做法,所以你应该为此声明一个常量。
private static final int STRING_NOT_IN_TEXT=-1;
/**
* @return first position of 's' in 'text'
* and if 's' is not in 'text' returns NOT_IN_TEXT
*/
public static int getStringPosition(final String s, final String[] text) {
for (int i = 0; i < text.length; i++) {
if (text[i].equals(s)) {
return i;
}
}
return STRING_NOT_IN_TEXT;
}
Ps您可能还想检查text
是否为null
并处理此情况,而不是简单地让系统抛出NullPointerReference
。
如果无法找到字符串构成错误 , 异常情况 ,那么您应该向调用者抛出一些异常。 例如,
throw new RuntimeException("String not found");
如果无法找到字符串是调用者想要在代码的正常流程中处理的正常情况,那么您应该使用特殊的返回值。 对于这种类型的搜索方法,没有正常的返回值可能是负数,并且约定是返回-1
,如String.indexOf
和List.indexOf
那样。 如果您遵循该约定,您实际上可以使用一行实现您的方法体:
return java.util.Arrays.asList(text).indexOf(s);
注意:该更改稍有不同地处理null
。 在您的方法中有三件事可能为null:搜索字符串,数组和数组元素。 如果传递空数组,或者当遇到null元素时,您当前的代码会抛出NullPointerException
,但会静默忽略空搜索字符串。 通过推迟到List.indexOf
,允许所有数组元素也为空,允许在数组中搜索空值。 这可能是一个无害的差异,但一个精心设计的方法会考虑这些问题。 例如,您可能更喜欢将空搜索字符串视为无效输入,并在这种情况下立即抛出异常。
完全记录的公共方法还会考虑数组中多个匹配元素的情况:它应该返回最低匹配索引还是任何匹配索引? 如果任何索引是可接受的,那么它是否必须始终为具有相同参数的重复调用返回相同的索引? (假设的多线程搜索实现很容易打败返回最低索引的“明显”假设,因为您无法预测哪个CPU核心将首先找到匹配。)
还要考虑该方法可以声明为static
。
这是武断的。 一些开发人员将抛出异常,其他人将返回一些特殊值,如-1。 最重要的是在任何情况下准确定义您的方法的作用,因此将使用您的代码的人知道他们正在使用的是什么。
我想到了两件事:
a)对于返回“索引”的方法非常有效,该索引指向任何类型的序列以返回-1以指示“找不到匹配”
b)抛出一些运行时异常(例如IllegalArgumentException)也可能是有效的
在考虑选项“b)”时,它有时会有两个方法,比如findIndex()和getIndex(); 按照惯例,“查找”方法总会引发异常; 而另一个会返回null / -1或其他值。 但是,当然,这是您在本地为您的项目/您的团队/您的任何内容定义的内容。 换句话说:所有处理代码的人都必须明白调用findXyz()可能会抛出异常; 并且还有其他方法不抛出。
而且,作为旁注,您应该始终尝试与“标准解决方案”保持一致。 我的意思是; 假设您的代码将使用集合:
int getIndex(String stringToSearch, List<String> stringsToSearch) {
return stringsToSearch.indexOf(stringToSearch);
猜猜这将返回什么......现在问问自己,你是否希望基于阵列的解决方案与java标准集合做同样的事情......
(最后的注意事项:是的,我的变量名称非常长,但我仍然认为冗长的名称比“s”更好......因为后者并没有告诉你关于这些参数的预期用途的任何信息)。
遵循常见和已知的编码约定:您的方法看起来像String.indexOf(String),因此在找不到输入时只返回-1。 例外应该是“例外”而不是在数组中找不到字符串。
如果你想要更多OO,你可以实现类似的东西
Result search(T something,Set<T> someSet);
使用接口结果由Found和NotFound类实现的处理方式不同; 一般来说,虽然这个解决方案看起来有点过分。
您不能返回null,因为您返回的是一个primite类型。 返回Integer而不允许null。
尽管如此,我同意上面的评论员,例外是处理这个问题的正确方法
如果没有找到,它是一个很好的模式返回null。 您可以使用Integer
而不是int
。 Integer
类在对象中包装基本类型int
的值。 Integer
类型的对象包含一个类型为int
字段。 这就是为什么你可以返回null,如果你喜欢它
public Integer getStringPosition(String s, String[] text)
但是,您可以使用此处的建议:
Integer
作为返回类型并返回null
值。 然而null
也被视为反模式(google“null十亿美元的错误”) 如果您不介意上述内容,请继续使用其中一个选项(许多程序员经常使用这些选项)
您还可以使用Optional / Maybe / Option类型
public Optional<Integer> getStringPosition(String s, String[] text) {
for (int i = 0; i < text.length; i++) {
if (text[i].equals(s)) {
Optional.of(i);
}
}
return Optional.empty();
}
Java 8中提供了Optional
。如果您使用的是旧版本,则可以使用许多可用实现之一(例如, https://google.github.io/guava/releases/19.0/api/docs/com/google /common/base/Optional.html )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.