Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rethrowing an Exception: Why does the method compile without a throws clause?

Tags:

On the source code below I'm rethrowing an Exception.
Why is it not necessary to put the throws keyword on the method's signature?

public void throwsOrNotThrowsThatsTheQuestion() {     try {          // Any processing      } catch (Exception e) {         throw e;     } } 
like image 270
cassiomolin Avatar asked Nov 11 '13 19:11

cassiomolin


People also ask

What is the purpose of Rethrowing an exception?

The purpose of the rethrow operation is to get the attention of the outside world that an exception has occurred and at the same time perform any contingency logic (such as logging) in the catch block.

How do you throw an exception without throws?

Without using throws When an exception is cached in a catch block, you can re-throw it using the throw keyword (which is used to throw the exception objects). If you re-throw the exception, just like in the case of throws clause this exception now, will be generated at in the method that calls the current one.

What is Rethrowing an exception in Java?

JavaObject Oriented ProgrammingProgramming. Sometimes we may need to rethrow an exception in Java. If a catch block cannot handle the particular exception it has caught, we can rethrow the exception. The rethrow expression causes the originally thrown object to be rethrown.

What is the purpose of throws clause in a method declaration?

The throws clause in a method declaration serves two purposes: It tells the compiler which exceptions are thrown so that the compiler can report uncaught (checked) exceptions as errors. It tells a programmer who is writing code that calls the method what exceptions to expect.


1 Answers

This behavior appears to occur only on Java 1.7. When compiling with 1.6, I get the following compiler error message:

c:\dev\src\misc>javac -source 1.6 Main.java warning: [options] bootstrap class path not set in conjunction with -source 1.6 Main.java:22: error: unreported exception Exception; must be caught or declared to be thrown         throw e;         ^ 1 error 1 warning 

But with Java 1.7, it compiles.

c:\dev\src\misc>javac -source 1.7 Main.java  c:\dev\src\misc> 

... Until I actually throw an Exception in the try block:

public static void throwsOrNotThrowsThatsTheQuestion() { try {      // Any processing     throw new IOException("Fake!");  } catch (Exception e) {     throw e; } 

Compiling...

c:\dev\src\misc>javac -source 1.7 Main.java Main.java:22: error: unreported exception IOException; must be caught or declare d to be thrown         throw e;         ^ 1 error 

It looks like Java 1.7 got smart enough to detect the kind of Exception(s) that might be thrown by analyzing the try block code, where as 1.6 just saw throw e; of type Exception and gave an error just for that.

Changing it to throw a RuntimeException made it compile as expected, because as always, unchecked Exceptions don't need a throws clause:

public static void throwsOrNotThrowsThatsTheQuestion() { try {      // Any processing     throw new RuntimeException("Fake!");  } catch (Exception e) {     throw e; } 

Compiling...

c:\dev\src\misc>javac -source 1.7 Main.java  c:\dev\src\misc> 

The Explanation

Here's what's going on:

Java 7 introduced more inclusive type checking. Quoting...

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:

(emphasis mine)

public void rethrowException(String exceptionName) throws FirstException, SecondException {   try {     // ...   }   catch (Exception e) {     throw e;   } } 
like image 79
rgettman Avatar answered Oct 16 '22 03:10

rgettman