Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catch a generic exception in Java?

We use JUnit 3 at work and there is no ExpectedException annotation. I wanted to add a utility to our code to wrap this:

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

So I tried this:

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

However, Java cannot use generic exception types in a catch block, I think.

How can I do something like this, working around the Java limitation?

Is there a way to check that the ex variable is of type T?

like image 705
Alex Baranosky Avatar asked Jun 11 '10 16:06

Alex Baranosky


People also ask

How do you catch generic exceptions?

Exception handling is used to handle the exceptions. We can use try catch block to protect the code. Catch block is used to catch all types of exception. The keyword “catch” is used to catch exceptions.

Should we catch generic exception Java?

As you can see in the following code snippet, even if you know which exceptions the method might throw, you can't simply catch them. You need to catch the generic Exception class and then check the type of its cause. This code is not only cumbersome to implement, but it's also hard to read.

What is generic exception in Java?

It refers to exception class that is near the top of the exception class hierarchy. Note that an exception class cannot be a generic class ... in the Java sense of generic types. The JLS says: "Note that a subclass of Throwable cannot be generic (§8.1.2)." -

What is generic catch?

Generics are not types. They are not templates. They are compile time type checks, in Java. Exception blocks catch on type. You can catch(Exception e) or even catch(Throwable e) and then cast as needed.


3 Answers

You could pass the Class object in and check that programatically.

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, //...

I'm not sure if you'd want the rethrow or not; rethrowing would equally fail/error the test but semantically I wouldn't, since it basically means "we didn't get the exception we expected" and so that represents a programming error, instead of a test environment error.

like image 85
Mark Peters Avatar answered Oct 19 '22 18:10

Mark Peters


I understand the impulse to try to simplify your exception-test idiom, but seriously: don't. Every possible choice you'll come up with is a cure that's worse than the disease. Especially JUnit 4's @ExpectedException nonsense! It is a too-clever frameworky solution, requiring everyone to learn how it works, as opposed to a plain self-evident bit of regular Java code. Worse, it gives you no way to wrap only the part of your test that you expect to throw the exception, so if an earlier setup step throws that same exception, your test will pass even though your code is broken.

I could write a long diatribe about this here (I'm sorry for not having enough time to), as we've had a lengthy discussion of this issue among Java engineers here at Google, and the consensus was that none of these crazy solutions are worthwhile. Get used to try/catch, it's really not that bad.

like image 33
Kevin Bourrillion Avatar answered Oct 19 '22 18:10

Kevin Bourrillion


Catch clause with type parameter is not possible:
http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotCatch

like image 44
oldo Avatar answered Oct 19 '22 17:10

oldo