26

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;
    }
}
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • are you sure you can do that for a checked exception?? – A4L Nov 11 '13 at 19:04
  • 1
    There seems to be a bug in Eclipse (Juno Service Release 1 Build id: 20121004-1855) as its not showing any error in your exemple. IntelliJ shows expected behavior (Unhandled exception error). Maybe that's what you are seing –  Nov 11 '13 at 19:08
  • a good post about checked vs unchecked exceptions:http://stackoverflow.com/questions/6115896/java-checked-vs-unchecked-exception-explanation – tokhi Nov 11 '13 at 19:21
  • you can even catch and rethrow `Throwable`. it's interesting that java7 is still not widely adopted and its features are not well known. but people would probably jump on java8 pretty fast. – ZhongYu Nov 11 '13 at 19:40

5 Answers5

35

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;
  }
}
rgettman
  • 176,041
  • 30
  • 275
  • 357
  • I wonder... is this related to the fact that Java 7 introduced multicatch statements? So that it's smart enough to interpret it as `catch (FirstException | SecondException e)` ? – Simon Forsberg Aug 10 '22 at 13:14
5

java.lang.Exception is a checked exception so this won't work or even compile. It would work with a unckeched (java.lang.RuntimeException). It makes absolutly no difference whether you throw an exception inside a catch block or not.

The compiler error would look something like this (depending on the compiler):

java: unreported exception java.lang.Exception; must be caught or declared to be thrown

EDIT: Java 7 can deal with such situations if you never actually throw the exception

maxammann
  • 1,018
  • 3
  • 11
  • 17
3

Why is not necessary to put the throws keyword on the method's signature?

You can put that cause your // Any processing is not throwing any checked-exception.

Example:

This compile fine.

public void throwsOrNotThrowsThatsTheQuestion() {
    try {

        throw new RuntimeException();

    } catch (Exception e) {
        throw e;
    }

This won't compile, you need to add throws clause.

public void throwsOrNotThrowsThatsTheQuestion() {
    try {
        throw new Exception();
    } catch (Exception e) {
        //do something like log and rethrow
        throw e;
    }
}

This is working since java 7. In previous version an exception is thrown. More information rethrow in java 7

nachokk
  • 14,363
  • 4
  • 24
  • 53
-1

When you use throws with a method, it means that the statement which will call that method must be surrounded with a try catch block.

But if the method already includes try catch block then no thorws declaration is needed as the exception being thrown by the method is being handled there only.

The statement calling this method does not need a to be surrounded with try catch block.

Hope this clears your doubt.

Bette Devine
  • 1,196
  • 1
  • 9
  • 23
  • 1
    The exception is not "being handled there only", because it _rethrows_ it. – ajb Nov 11 '13 at 19:16
  • I think you mis read what I said @ajb. Please go through it again and understand each word which I have written. Then make a decision. – Bette Devine Nov 12 '13 at 02:51
  • OK, I did. My decision is that what you wrote is pretty vague--when you use the word "method", I don't know whether you mean the method in the post, a method called by that method, or a method that calls the method. Anyway, we've already determined that `throwsOrNotThrowsThatsTheQuestion` may or may not need a `throws` declaration depending on what's in the "Any processing" code. – ajb Nov 12 '13 at 03:53
  • By your words, it seems like you understood what I meant and what is included in the post. I just needed the same. Thanks :) – Bette Devine Nov 12 '13 at 04:51
-1

throw new Exception(); is something you should never do in a catch block, but you may have to or want to do throw new SomeException(throwable); (preserving the full stack trace) instead of throw throwable; in order to conform to the API of your method, e.g. when it declares to throw SomeException but you're calling code that might throw an IOException that you don't want to add to you method's throws clause.

The probably most common case is new RuntimeException(throwable); to avoid having a throws clause altogether.

tokhi
  • 21,044
  • 23
  • 95
  • 105