遇到可预测但不可避免的故障的方法的首选设计是什么? 他们应该返回空结果还是在失败时抛出异常?请解释一下你的推理。
我将提供两种示例方法:
Tickets.buy(20, 100)
。票务机器人尝试使用100美元购买至少20张票。该方法返回已购买的票证列表。对于这两种方法,我们假设用户无法预测该方法是否能成功找到匹配。
如果出现以下情况,方法1可能会失败:
如果出现以下情况,方法2可能会失败:
Java选择将等效项返回给方法1的空结果,但对方法2执行相同操作不允许您区分这两种错误。选择两种可能的设计有哪些指导原则?
请注意,虽然这个问题包含两个具体方法,但我正在寻找一般设计指南,而不是上述方法的具体解决方案。
答案 0 :(得分:1)
最好的方法取决于案例。
案例1:
由于该方法返回找到的元素的索引,如果找不到所需的值,我建议返回-1
。坚持几乎每个人都熟悉的众所周知的API,比如indexOf()
。
案例2:
在这里,我建议使用例外(InsufficientMoneyException
,OutOfTicketsException
,...)。空列表或null
不是很有意义,并且不能反映不同的错误情况。
这样您就可以在各自的catch块中正确处理异常。
通常,您必须记住,抛出异常是昂贵的操作,因为必须构建堆栈跟踪。
答案 1 :(得分:1)
这个问题基于意见,就像整个返回null /抛出异常/返回空对象困境一样。
我个人认为返回-1
是第一种方法,为第二种方法抛出异常会更好。
在single responsibility principle之后,一种方法应该做一件事。
第一种方法的目标是搜索一个元素,它可以找到或找不到它。这是预期行为。
第二种方法的目标是买票。与第一种方法不同,它不是检查,如果它可以买票,它就是这样做的。预期的行为是购买机票。 如果该行为未发生,则出现问题,因此应抛出异常。
我也认为@ StriplingWarrior的方法可能并不理想,因为如果你不仅仅有两种可能的情况,你就不可能Either<A, B, C, D, E, ...>
。
RIP。我花了15分钟写了一个答案,我意外地打开了Web控制台并删除了正文。最后保存的答案就像10分钟前一样。我甚至不知道你怎么会意外地这样做。我猜F12
和DEL
有点接近
答案 2 :(得分:0)
通常,您希望将返回类型设为包含您可能需要了解的所有信息的对象。
在Java的早期阶段,通常会返回通常无效的值,例如-1
(在Arrays.binarySearch()
}或null
的情况下),以表示缺少值。更现代的API倾向于返回Optional<>
以提供可能没有结果的概念的编译时执行(以及区分&#34;没有结果&#34;和&#34;结果是null
)。
在Tickets.buy()
示例中,您可以拥有Either<String, List<Ticket>>
,其中&#34;左边&#34;价值可能是购买失败的原因,并且&#34;权利&#34; value可以是成功购买的门票。
答案 3 :(得分:0)
我最终接受了https://stackoverflow.com/a/77361/14731
中的建议我的解释如下:
Arrays.binarySearch()
的目的是返回数组中元素的索引,那么当找不到匹配项时它应该抛出异常。没有结果具有负索引的事实是一个方便的事实,它允许我们返回-1。但同样,在理想世界中,这种方法应该抛出异常。如果此方法回答“数组是否包含此元素”并返回boolean
这一问题,那么就不需要抛出任何异常。Tickets.buy(20, 100)
假设在购买门票时会找到匹配项。如果未找到匹配项,则应抛出异常。