包装已检验 Java 异常的标准方法
我有一个相当详细的问题,关于包装检查异常的正确方法,以及番石榴的做法。(为长度道歉,但我想把我的思维过程放下来)
标准界面如下所示:Runnable
public interface Runnable
{
public void run();
}
其中不能引发已检查的异常。run()
因此,如果我想有一个用于包装引发已检查异常的任务的哪个,并且我打算让调用来处理这些异常的东西,而不是本身,我必须将异常包装在未经检查的异常中。Runnable
Runnable.run()
Runnable.run()
所以有一段时间我一直在使用:
Runnable r = new Runnable {
@Override public void run()
{
try {
doNastyStuff();
}
catch (NastyException e)
{
throw new RuntimeException(e);
}
}
};
然后我可以在上层处理。除了那时我想,我真正想要的是单独处理一个包装的异常,因为我知道它的语义是包装一个检查的异常,所以我写了这个帮助器类:RuntimeException
/**
* Wrapped exception: the purpose of this is just to wrap another exception,
* and indicate that it is a wrapped exception
*/
public class WrappedException extends RuntimeException
{
/**
* @param t any throwable
*/
public WrappedException(Throwable t)
{
super(t);
}
}
然后我可以这样做:
/* place that produces the exception */
...
catch (NastyException e)
{
throw new WrappedException(e);
}
...
/* upper level code that calls Runnable.run() */
try
{
...
SomeOtherNastyCode();
r.run();
...
}
catch (SomeOtherNastyException e)
{
logError(e);
}
catch (WrappedException e)
{
logError(e.getCause());
}
它似乎工作得很好。
但是现在我在想,好吧,如果我想在库以及使用库的应用程序中使用它,现在它们都依赖于,所以它应该真正存在于一个基础库中,我可以将其包含在任何地方。WrappedException
这让我想到,也许番石榴在某个地方有一个标准类,因为我现在默认将番石榴作为依赖项。所以我可以做WrappedException
throw new WrappedException(e);
或
throw Exceptions.wrap(e);
或
Exceptions.rethrow(e);
我刚刚在番石榴中环顾四周,发现Storables
具有看起来很相似的Throwables.propagate(),
但它只是将检查的异常包装在,而不是一个特殊的子类中。RuntimeException
RuntimeException
哪种方法更好?与 ?我的顶级代码想知道增加信息价值的最顶层异常。WrappedException
RuntimeException
如果我有一个 包装 a 包装 a ,包装不会增加信息价值,我不在乎它,所以我会记录的错误将是 .RuntimeException
NastyException
NullPointerException
RuntimeException
NastyException
如果我有一个 包装 a ,通常会增加信息价值。IllegalArgumentException
NastyException
IllegalArgumentException
因此,在我执行错误日志记录的顶级代码中,我必须执行如下操作:
catch (RuntimeException re)
{
logError(getTheOutermostUsefulException(re));
}
/**
* heuristics to tease out whether an exception
* is wrapped just for the heck of it, or whether
* it has informational value
*/
Throwable getTheOutermostUsefulException(RuntimeException re)
{
// subclasses of RuntimeException should be used as is
if (re.getClass() != RuntimeException)
return re;
// if a runtime exception has a message, it's probably useful
else if (re.getMessage() != null)
return re;
// if a runtime exception has no cause, it's certainly
// going to be more useful than null
else if (re.getCause() == null)
return re;
else
return re.getCause();
}
这种理念对我来说是正确的,但实现感觉很糟糕。有没有更好的方法来处理包装的异常?
相关问题: