我想设计一个API,其中我有两个版本的同一方法extractLastElement()
:
第一个版本将没有throws属性:Object extractLastElementSafe();
将在客户端“肯定知道” 包含集合中的元素(例如,他已经刚刚添加了一些元素,因此不需要try-catch样板代码。
第二个版本将引发Checked Exception:Object extractLastElement() throws NoMoreElementsException
;如果客户端不确定集合中是否还有剩余元素(例如在循环内),将由客户端使用。
这被认为是不好的设计吗?有没有其他替代方法可以模仿这种行为?
public class SomeCollection {
private List<String> arr;
public SomeCollection(List<String> arr) {
this.arr = arr;
}
public String extractLastElementSafe() {
return arr.remove(arr.size() - 1);
}
public String extractLastElement() throws NoElementsLeftException {
try {
return arr.remove(arr.size() - 1);
} catch (IndexOutOfBoundsException e) {
throw new NoElementsLeftException(e); // throwing a checked exception
}
}
}
class NoElementsLeftException extends Exception {
public NoElementsLeftException(Throwable cause) {
super(cause);
}
}
答案 0 :(得分:4)
赋予用户以不同方式做相同事情的能力总是有问题的。强迫客户担心最后一个元素是否存在也不太好。
但是最后,这更多是一种风格,您的方法可以认为还可以。尽管如此,您仍然向客户端公开了调用“安全”方法的方法,并最终导致运行时异常。因此,实际上实际上有两种不同的错误情况。
必须改变的一件事:避免代码重复!执行try / catch引发该异常的方法应该只调用“安全”方法!
说了这么多:我个人只提供一种抛出某些运行时异常的方法。标准Java集合使用未经检查的异常,您也应该这样做。
引用罗伯特·马丁的话:“已检查和未检查的异常之间的战争已经结束,未检查的异常赢得了胜利”。他在十多年前写了这封信。
答案 1 :(得分:1)
如果每种方法的版本都有明确定义的使用方案,则应同时使用这两种方法。此类设计决策的示例可以在类Queue中找到,该类在两种模式下工作,例如,尝试从空队列中删除元素时:一种方法(poll
)返回null,而另一种方法返回null。 (remove
)引发异常。