在Java中捕获一般的异常?

时间:2010-06-11 16:54:32

标签: java generics exception

我们在工作时使用JUnit 3,没有ExpectedException注释。我想在我们的代码中添加一个实用程序来包装它:

 try {
     someCode();
     fail("some error message");
 } catch (SomeSpecificExceptionType ex) {
 }

所以我尝试了这个:

public static class ExpectedExceptionUtility {
  public static <T extends Exception> void checkForExpectedException(String message, ExpectedExceptionBlock<T> block) {
     try {
        block.exceptionThrowingCode();
        fail(message);
    } catch (T ex) {
    }
  }
}

但是,我认为Java不能在catch块中使用泛型异常类型。

我如何做这样的事情,解决Java限制?

有没有办法检查ex变量的类型为T

7 个答案:

答案 0 :(得分:28)

您可以传递Class对象并以编程方式检查它。

public static <T extends Exception> void checkForException(String message, 
        Class<T> exceptionType, ExpectedExceptionBlock<T> block) {
    try {
       block.exceptionThrowingCode();
   } catch (Exception ex) {
       if ( exceptionType.isInstance(ex) ) {
           return;
       } else {
          throw ex;  //optional?
       }
   }
   fail(message);
}

//...
checkForException("Expected an NPE", NullPointerException.class, //...

我不确定你是否想要重新抛出;重新抛出同样会失败/错误测试但在语义上我不会,因为它基本上意味着“我们没有得到我们预期的异常”,因此这代表编程错误,而不是测试环境错误。

答案 1 :(得分:4)

我理解尝试简化异常测试习惯的冲动,但严重的是:不要。你想出的每一个可能的选择都是比疾病更糟糕的治疗方法。 特别是 JUnit 4的@ExpectedException废话!这是一个过于聪明的框架式解决方案,需要每个人都能学习它是如何工作的,而不是普通的Java代码。更糟糕的是,它无法仅包装您希望抛出异常的测试部分,因此如果早期的安装步骤抛出相同的异常,即使您的代码被破坏,您的测试也会通过。

我可以在这里写一篇很长的诽谤(我很抱歉没有足够的时间),因为我们在谷歌的Java工程师中对这个问题进行了长时间的讨论,并且达成的共识是这些疯狂的解决方案是值得的。习惯尝试/捕捉,它真的没那么糟糕。

答案 2 :(得分:1)

泛型不是类型。它们不是模板。它们是Java中的编译时类型检查。异常块捕获类型。您可以捕获(例外e)甚至捕获(Throwable e)然后根据需要进行投射。

答案 3 :(得分:0)

好吧,如果它不是预期的异常,你可以捕获异常并重新抛出。虽然良好的编码实践通常要求代码的成功路径不应该由异常定义,因此您可能需要重新考虑您的设计。

答案 4 :(得分:0)

您还可以使用支持实时模板的IDE(如IntellJ IDEA for instance)并指定一个快捷方式,如ee -> [tab],为您插入try / catch / ignore,并让您输入正确的。

like this http://img80.imageshack.us/img80/433/capturadepantalla201006j.png

like this http://img641.imageshack.us/img641/6733/capturadepantalla201006w.png

答案 5 :(得分:0)

答案 6 :(得分:0)

@FunctionalInterface
 public interface ThrowingConsumer<T, E extends Exception> {
      void accept(T t) throws E;
 }
public static <T, E extends Exception> Consumer<T> errConsumerWrapper(ThrowingConsumer<T, E> throwingConsumer,
                   Class<E> exceptionClass, 
                   Consumer<E> exceptionConsumer) {
            return i -> {
                try {
                    throwingConsumer.accept(i);
                } catch (Exception ex) {
                    try {
                        exceptionConsumer.accept(exceptionClass.cast(ex));
                    } catch (ClassCastException ccEx) {
                        throw new RuntimeException(ex);
                    }
                }
            };
        }
  1. 用法示例

    Stream.of(“ a”)。forEach(errConsumerWrapper(i-> Integer.parseInt(i), NumberFormatException.class, Throwable :: printStackTrace));