Exceptions { public static Throwable firstCauseNotOf(Throwable ex, Class<?>... types) { boolean typeMatched = false; for (Class<?> type : types) { if (type.isInstance(ex)) { typeMatched = true; break; } } if (!typeMatched) { return ex; } Throwable cause = ex.getCause(); if (cause != null) { return firstCauseNotOf(cause, types); } return null; } private  Exceptions(); static Throwable rootCause(Throwable ex); static T anyCauseOf(Throwable ex, Class<T> type); static Throwable firstCauseNotOf(Throwable ex, Class<?>... types);  }
@Test public void testFirstNot() { A top=new A("a",new B("b",new D("d",new B("root")))); Throwable anyCauseOf = Exceptions.firstCauseNotOf(top,B.class,A.class); Assert.assertEquals("type", D.class,anyCauseOf.getClass()); Assert.assertEquals("message", "d",anyCauseOf.getMessage()); anyCauseOf = Exceptions.firstCauseNotOf(top,B.class,D.class,A.class); Assert.assertNull(anyCauseOf); anyCauseOf = Exceptions.firstCauseNotOf(top,D.class,B.class); Assert.assertEquals("type", A.class,anyCauseOf.getClass()); Assert.assertEquals("message", "a",anyCauseOf.getMessage()); }