3

My question is a follow-up to this question:

Why doesn't Java allow generic subclasses of Throwable?

The question was answered perfectly, but only on indirect generic exception, that's:

public class MyException<T> extends Exception {

What was left void, is direct generics:

public static <T extends Exception> void checkForException(Class<T> exType) {

    try {
        // some code
    } catch (T e) {
        e.printStackTrace();
    }
}

Why is this not allowed?

Though, the only reason I could think this is not allowed, is that T could be a type, that is also explicitly caught:

// if T is IOException
catch(T e) { }
catch(IOException e) { }

But is this a good reason to block it? The same effect, could as well be done without generics too:

catch(Exception e) { }
catch(IOException e { }

Here's the documentation of the above restriction.

Community
  • 1
  • 1
Mordechai
  • 13,232
  • 1
  • 32
  • 69

2 Answers2

0

If our exception type is generic, we don't know the actual type at compile time, and at runtime, the type is erased. throwing such an exception is possible because the Class<T> allows us to construct an instance, but catching must know the type to match at compile time. However it cannot know the type, because it's not specified at the catch site.

llogiq
  • 11,855
  • 3
  • 36
  • 65
0

Because in Java Type Variables, i.e. T, are not reifiable due to Type Erasure.

This means the compiler does not have T at runtime at all.

Hence there is no way that catch block of yours will ever know what T originally was. And no, you can't just treat it as the base type. That would do something completely different. What if you had

catch(T e) { }
catch(MyBaseException e) { }
catch(MyApplicationException e) { }

and T extends MyBaseException. See how that got really bad really quick?

Read more in the excellent Java Generics FAQs - Under The Hood Of The Compiler

Personally I've never liked type erasure, but the language designers swore they had their reasons for using it. So here we are.

Community
  • 1
  • 1
kervin
  • 11,246
  • 5
  • 38
  • 57