Deepankar Singh
Deepankar Singh

Reputation: 674

Reassignment of an Exception to the catch parameter

Consider the following code.

import java.io.IOException;
import java.sql.SQLException;

public class ReassignmentICatch {

    public void couldThrowAnException() throws SQLException, IOException {}
    public void rethrow() throws SQLException, IOException {
      try {
         couldThrowAnException();
         System.out.println("Did not throw");
      } catch (Exception e) {   //Line-1
        e = new IOException();  //Line-2    
        throw e;                //Line-3        
      }
    }

    public static void main(String[] args) {
        ReassignmentICatch rc = new ReassignmentICatch();
        try {
            rc.rethrow();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

As i know catch(Exception e) in java7 does not catch all exceptions like java6 instead it catches only those exceptions which are mentioned in the declaration of method couldThrowAnException. Also Reassigning a new exception to the catch parameter(e) is not allowed that's why we get compilation error at Line-3

Is this reassignment not allowed in java6 too. I thought it should be allowed to reassign in java6 so i changed the property of java-compiler in eclipse and set compliance level to 1.6 to see whether this code compiles or not.

The behaviour that i am not able to predict is:
1.Eclipse is giving same error

Unhandled exception type Exception

for java 6 7 and 8.

2.When i am trying with command line using javac -target 1.6 -source 1.6 ReassignmentICatch.java am getting

warning: [options] bootstrap class path not set in conjunction with -source 1.6 ReassignmentICatch.java:18: error: unreported exception Exception; must be caugh t or declared to be thrown

  throw e;
  ^ 1 error 1 warning 

and with java7 and java8 i am able to compile and run it successfully with output Did not throw .Why IDE and command-line are not giving same result.

Can somebody please suggest me what I am missing here.
Thanks.

Upvotes: 3

Views: 1189

Answers (3)

Deepankar Singh
Deepankar Singh

Reputation: 674

As suggested by 11thdimension in java-6 compilation is not possible because the static type of catch parameter e is still Exceptioneven if a new IOEXception() is assigned to e, so cannot be handled by just declaring IOException in the method declaration. Where as in Java-7 using Exception e in catch works fine
For example the following program cannot be compiled on pre-java7 compiler.

import java.io.IOException;

public class ExampleExceptionRethrowSE7

{
    public static void demoRethrow() throws IOException {
    try {


        throw new IOException("Error");
    }
    catch(Exception exception) {
        /*

         * Do some handling and then rethrow.
         */
        throw exception;
    }
   }

    public static void main(String[] args) {
        try {
            demoRethrow();
        }

        catch (IOException exception) {
            System.err.println(exception.getMessage());
        }
    }
}


The reason why the throw e statement in the posted code is causing error is we cannot reassign an exception to the catch parameter e, the same restriction that we face in multi-catch.

The difference between this and multi- catch is where the compiler error occurs. For multi-catch, the compiler error occurs on the line where we attempt to assign a new value to the parameter, whereas here, the compiler error occurs on the line where we throw e. It is different because code written prior to Java 7 still needs to compile. Since the multi- catch syntax is brand new, there is no legacy code to worry about.

PS: Command line and eclipse is giving the same consistent error now. I don't know what was going wrong earlier in command line. :P

Upvotes: 0

11thdimension
11thdimension

Reputation: 10653

I'm not sure about what you mean by that Java 6 and Java 7 are different in how they catch exceptions as I'm not aware of anything like that, can you post a reference ?

Exceptions mentioned in method declaration are throws clause exceptions. These are the exceptions that method itself doesn't catch but wants it's caller to catch.

You should not be getting error when assigning to catch variable. The error that you're getting however is because you're throwing an Exception type and it's not declared in the throws clause.

Consider code below

e = new IOException();  //Line-2    
throw e;                //Line-3

Even though you've assigned e IOException instance, type of e is still Exception. Which is not caught and not declared in throws clause and thus reported as error.

There are two solutions for it. You can either declare Exception in the throws clause or typecast e before throwing it.

public void rethrow() throws SQLException, IOException
//becomes
public void rethrow() throws Exception

or

throw e;
//becomes
throw (IOExceptoin)e;
//or
throw new IOException();

Edit*

The difference between Java 6 and Java 7 as given in your link is that Java 7 is capable of deducing exception type at compile time. Even if it's assigned to a Super class type Java 7 will be able to deduce it's original type and not will not complain. This saves us from having to wrap the exception object into a RuntimeException object.

Most likely the reason of difference in your Eclipse and command line output is that you haven't modified the compiler settings in the Eclipse for different Java versions. When changing a Java version for a project in Eclipse you need to change following

  1. Java System Library in build path
  2. Compiler source compliance (Preferences>Java>Compiler>Compiler compliance level)

After making both the changes you should be able to see correct behavior.

Upvotes: 3

stys
stys

Reputation: 727

There are two types of exceptions in java: checked exceptions (inherited from Exception) and unchecked exceptions (inherited from RuntimeExceptions).

Checked exceptions must be handled inside the method or declared to be thrown in the method signature. That is why rethrowing the Exception still gives you a compilation error.

Typically rethrowing an exception is done by wrapping into RuntimeException:

try {
    doSomething();
} catch (Exception ex) {
    throw new RuntimeException(ex);
}

Check this very good tutorial on Java Exceptions http://tutorials.jenkov.com/java-exception-handling/index.html

Upvotes: 0

Related Questions