简体   繁体   中英

Why try/catch around throwable?

In trying to refactor some I code I attempted to throw the exception in the catch clause like so -

try {
....
}
catch(Exception exception){
.....
throw exception
}

However when I attempted to throw the exception on line "throw exception" the compiler complained with a message that I needed to surround my throw clause in a new try/catch like so -

try
{
  ....
}
catch (Exception exception)
{
  .....
  try
  {
    throw exception
  }
  catch (Exception e2)
  {
     ...
  }
}

Why does the compiler require this and what use does it provide ?

Thanks

The exception java.lang.Exception is a checked exception. This means that it must either be declared in the throws clause of the enclosing method or caught and handled withing the method body.

However, what you are doing in your "fixed" version is to catch the exception, rethrow it and then immediately catch it again. That doesn't make much sense.

Without seeing the real code, it is not clear what the real solution should be, but I expect that the problem is in the original try { ... } catch handler:

  • If possible, you should catch a more specific exception at that point, so that when you rethrow it, it is covered by the method's existing throws list.

  • Alternatively, you could wrap the exception in an unchecked exception and throw that instead.

  • As a last resort, you could change the signature of the method to include Exception in the throws list. But that's a really bad idea, because it just pushes the problem off to the caller ... and leaves the developer / reader in the position of not knowing what exceptions to expect.

In your original code, nothing catches the thrown exception. I would imagine you either have to specify that your function throws an exception or have another try/catch block as the compiler suggests to catch it.

Instead of

public void yourFunction(){
  try {
    ....
  }
  catch(Exception exception){
    .....
    throw exception
  }
}

try

public void yourFunction() throws Exception{
  try {
    ....
  }
  catch(Exception exception){
    .....
    throw exception
  } 
}

In Java, there is a distinction between checked and unchecked exceptions. An unchecked exception can essentially be thrown at any place in code and, if it's not caught somewhere, it will propagate up to the entry point of your application and then stop the process (usually with an error message and stack trace). A checked exception is different: The compiler won't let you just let it propagate, you need to either surround any code which might throw a checked exception with try-catch blocks (and "throw exception" is the simplest case if exception is an instance of a checked exception class) or you must mark the method which contains the call to code that might throw a checked exception with a "throws" declaration. If the desired behaviour is to throw an unchecked exception, then you'll need to wrap the exception in a RuntimeException. If the desired behaviour is to keep the exception checked, then you'll need to add a throws declaration to your current method.

My guess is that your trying to throw an exception sub class that isn't declared by the method as an exception type it can throw.

The following example works

package test.example;

public class ExceptionTest {

    public static void main(String[] args) throws Exception{
        try {
            int value = 1/0;
        } catch (Exception e) {
            System.out.println("woops the world is going to end");
            throw e;
        }

    }

}

However this example will give an error.

package test.example;

public class ExceptionTest {

    public static void main(String[] args) throws RuntimeException{
        try {
            int value = 1/0;
        } catch (Exception e) {
            System.out.println("woops the world is going to end");
            throw e;
        }

    }

}

Note in the second example I'm simply catching Exception not RuntimeException, it won't compile as I throw Exception which is an undeclared throws, even though I do declare RuntimeException.

Yes the exception is a RuntimeException but the compiler doesn't know that.

Just thought of a third working example to show you. This one also works because your throwing the same type as you declare. (note the only change is the catch block)

package test.example;

public class ExceptionTest {

    public static void main(String[] args) throws RuntimeException{
        try {
            int value = 1/0;
        } catch (RuntimeException e) {
            System.out.println("woops the world is going to end");
            throw e;
        }

    }

}

You need to understand the differences between all three of these answers

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM