我们的项目中有一个BaseException extends Exception
,基本上所有其他异常都来自这个类。我想更改一些在运行时处理"原因堆栈"的方法。
作为起点,我编写了以下方法:
class BaseException extends Exception {
...
/**
* Helper: creates a list containing the complete "cause stack" of this exception.
* Please note: the exception on which this method is called is part of result!
*
* @return a {@link List} of all "causes" of this exception
*/
List<Throwable> getAllCauses() {
Throwable cause = this;
List<Throwable> causes = new ArrayList<>();
while (cause != null) {
causes.add(cause);
cause = cause.getCause();
}
return causes;
}
这完成了工作,尽管它并不完美(名称不是很好,并且也违反了单层抽象(。
但是:有没有一种"更优雅"的方式来收集这个结果?特别是考虑到直接返回Stream<Throwable>
会有所帮助。
(我主要想知道是否有一个java8 lambda/习语可以在这里提供帮助(
这篇文章应该会有所帮助。特别
Stream<Throwable> causes(Throwable t){
if (t == null) return Stream.empty();
return Stream.concat(Stream.of(t), causes(t.getCause()));
}
这是我由Spliterator实现的实现,如下所示:
public static <T> Stream<T>
iterateUntil(T seed, UnaryOperator<T> generator, Predicate<T> proceed){
return stream(new AbstractSpliterator<T>(Long.MAX_VALUE, Spliterator.ORDERED){
private T value = seed;
public boolean tryAdvance(Consumer<? super T> action){
if(!proceed.test(value)) return false;
action.accept(value);
value = generator.apply(value);
return true;
}
}, false);
}
然后,您可以按如下方式实现getCauses
,并删除递归调用:
List<Throwable> getAllCauses() {
return iterateUntil(this, Throwable::getCause, Objects::nonNull)
.collect(toList());
}
使用一些枚举对我来说似乎更合适,然后像
class BaseException extends Exception {
...
Enumeration<Throwable> getCauses() {
return new Enumeration<Throwable>() {
private Throwable current = BaseException.this;
public boolean hasMoreElements() {
return current != null;
}
public Throwable nextElement() {
Throwable c = current;
current = current.getCause();
return c;
}
}
}
在 Java 8 中,您还可以使用默认方法创建一个新接口,然后在任何异常类中使用该接口(比子类化稍微好一点Exception
?(。