我对使用Java创建API有疑问。假设我有一个课程如下: -
class Test
{
public final static String DEFAULT_ENCODING = "utf-8";
public byte[] encodeIt(String input)
{
try {
return input.getBytes(DEFAULT_ENCODING);
} catch(UnsupportedEncodingException e) {
// do something
}
}
}
我知道UnsupportedEncodingException
永远不会出现,因为我使用静态字符串作为toBytes
的输入。让encodeIt
执行throws UnsupportedEncodingException
是没有意义的,因为我不希望API用户期望并捕获该错误。
在这种情况下,最好的做法是设置空挡块吗?
答案 0 :(得分:5)
我这样做:
public byte[] encodeIt(String input) {
try {
return input.getBytes(DEFAULT_ENCODING);
}
catch (UnsupportedEncodingException e) {
throw new ShouldNeverHappenException(e);
// or: throw new IllegalStateException(e);
}
}
(当然,ShouldNeverHappenException是运行时异常)。
这样,如果有人碰巧更改了常量值,或者添加了编码参数,该方法将快速失败,并且问题不会被忽视或隐藏在日志文件中。
答案 1 :(得分:5)
拥有空的catch块是一个坏主意。即使你的推理看起来是正确的,这个设计在某个阶段会导致你无休止的调试和搜索,一旦异常开始发生,你的代码就会吞下它们。我会把你的异常包装在RuntimeException中并抛出它。像这样:
public encodeIt(String input)
{
try {
return input.getBytes(DEFAULT_ENCODING);
catch(UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
这样一来,如果您的异常发生,您的异常就不会隐藏,也不会让您的API用户满足它。
答案 2 :(得分:3)
在这种情况下,最好的做法是设置空挡块吗?
我觉得这不是一个好主意。空捕获块意味着可能发生某些事情,你永远不会知道。
不要抛出此异常。抓住并记录它,这样你就可以检查你的假设它永远不会发生,但至少你会知道它是否永远不会到来。
答案 3 :(得分:2)
我通常会遵循此问题的其他答案所概述的策略(例如将已检查的异常软化为RuntimeException
)。但是,一个有趣的选择是使用断言:
public byte[] encodeIt(String input)
{
try {
return input.getBytes(DEFAULT_ENCODING);
} catch(UnsupportedEncodingException e) {
assert false;
return null;
}
}
当使用-ea
JVM标志启用断言时,如果抛出AssertionError
,此方法将抛出UnsupportedEncodingException
。烦恼是需要返回一个值(例如null),否则代码将无法编译。
所以也许以下是“更好”:
public byte[] encodeIt(String input)
{
try {
return input.getBytes(DEFAULT_ENCODING);
} catch(UnsupportedEncodingException e) {
throw new AssertionError("Unexpected.", e);
}
}
除了RuntimeException
很好地自我记录之外,与抛出AssertionError
并没有太大的不同。并且,作为Error
的子类,它代表了比Exception
通常所暗示的更基本的失败。没有机会在处理这个东西的堆栈上某个更高的catch (Exception e)
子句(它是否会发生)。
答案 4 :(得分:1)
我认为最好的方法是避免检查异常。只需使用未经检查的。然后你将充分利用2个世界:如果确实发生错误,你会发出错误的信号,你不会强迫API的用户处理异常。
答案 5 :(得分:0)
如果您非常非常确定它永远不会发生,请留下一个空的挡块。 但是对于练习,以防万一你以后更改代码,最好在发生异常时将其记录到控制台。