-1

why does this work

class blah{
    public void someMethod(){
        try{
            throw new NullPointerException();
        }
        catch(Throwable t){
            System.out.println("Caught!");
            throw t;
        }
    }
}

it seems like the compiler some how see the actual type of t

Adam Kipnis
  • 10,175
  • 10
  • 35
  • 48

3 Answers3

0

It works because NullPointerException is an instance of Throwable. The catch clause catches all instances of the declared type.

Dorian Gray
  • 2,913
  • 1
  • 9
  • 25
  • You can't normally `throw` a `Throwable` (i.e. `t`) without catching it (`catch`) or declaring it (`throws Throwable`), since it is neither a `RuntimeException` or an `Error`. – Andreas Apr 19 '18 at 18:00
  • I never said you can do so. – Dorian Gray Apr 19 '18 at 18:03
  • The question is why `throw t` doesn't fail to compile, given that it is *declared* to be of type `Throwable`, which is not one of the two unchecked types (`RuntimeException` and `Error`). – Andreas Apr 19 '18 at 18:06
  • Because `Throwable` is the superclass of them. – Dorian Gray Apr 19 '18 at 18:10
  • But `Throwable` itself is a *checked* type, so question is "why does this work", i.e. why does `throw t` not complain that the checked `Throwable` is not caught or declared? You are not answering that at all. – Andreas Apr 19 '18 at 18:16
  • I'm not sure what you're actually saying, since `NullPointerException`, being an instance of `RuntimeException`, doesn't need to be caught or declared, the question isn't why that part works. The question is (paraphrased): *Why does this work? It seems like the compiler some how see the actual type of `t`, i.e. that `t` is not a `Throwable` but a `NullPointerException`, so throwing `t` is ok, because otherwise throwing a `Throwable` would be a compile error.* – Andreas Apr 19 '18 at 18:16
  • Im not quite sure what the point of the question is, I thought it is about the `catch(Throwable t)` clause. That works because `NullPointerException` is an instance of `Throwable`. – Dorian Gray Apr 19 '18 at 18:21
  • It's about the `throw t` statement, which will fail to compile before Java 7, because `Throwable` (the declared type of `t`) is a **checked** type. – Andreas Apr 19 '18 at 18:27
  • Ah, well, it would have been helpful if the first post would have said so. – Dorian Gray Apr 19 '18 at 18:28
  • If by "first post" you mean my first comment, then I did specifically mention `throw` of `t`. – Andreas Apr 19 '18 at 18:30
  • No, I meant the person who asked that question. – Dorian Gray Apr 19 '18 at 18:30
0

That code will fail to compile before Java 7.

From the Java SE 7 Features and Enhancements, section Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking:

Rethrowing Exceptions with More Inclusive Type Checking

The Java SE 7 compiler performs more precise analysis of rethrown exceptions than earlier releases of Java SE. This enables you to specify more specific exception types in the throws clause of a method declaration.

Consider the following example:

static class FirstException extends Exception { }
static class SecondException extends Exception { }

public void rethrowException(String exceptionName) throws Exception {
  try {
    if (exceptionName.equals("First")) {
      throw new FirstException();
    } else {
      throw new SecondException();
    }
  } catch (Exception e) {
    throw e;
  }
}

This examples's try block could throw either FirstException or SecondException. Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. In releases prior to Java SE 7, you cannot do so. Because the exception parameter of the catch clause, e, is type Exception, and the catch block rethrows the exception parameter e, you can only specify the exception type Exception in the throws clause of the rethrowException method declaration.

However, in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration. The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either FirstException or SecondException:

public void rethrowException(String exceptionName)
throws FirstException, SecondException {
  try {
    // ...
  }
  catch (Exception e) {
    throw e;
  }
}
Community
  • 1
  • 1
Andreas
  • 154,647
  • 11
  • 152
  • 247
-1

NullPointerException is a child of Excepsion. Exception is a child of Throwable. So thats should work becouse of Polymorphism.

  • You can't normally `throw` a `Throwable` (i.e. `t`) without catching it (`catch`) or declaring it (`throws Throwable`), since it is neither a `RuntimeException` or an `Error`. – Andreas Apr 19 '18 at 18:01