我们的项目中有一个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;
}
这可以完成工作,虽然它并不完美(名称并不完美,并且也违反了单层抽象)。
但仍然:是否有更优雅的#34;收集这个结果的方法?特别是考虑到直接返回Stream<Throwable>
会有帮助的事实。
(我主要想知道是否有一个java8 lambda / idiom可以帮助到这里)
答案 0 :(得分:10)
This文章应该有所帮助。特别是,
Stream<Throwable> causes(Throwable t){
if (t == null) return Stream.empty();
return Stream.concat(Stream.of(t), causes(t.getCause()));
}
答案 1 :(得分:4)
以下是我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());
}
答案 2 :(得分:1)
使用一些枚举似乎更适合我,然后像
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
?)。