try/catch versus throws Exception

Are these code statements equivalent? Is there any difference between them?

private void calculateArea() throws Exception {
....do something
}

private void calculateArea() {
try {
....do something
} catch (Exception e) {
showException(e);
}
}
102460 次浏览

Yes, there's a huge difference - the latter swallows the exception (showing it, admittedly), whereas the first one will let it propagate. (I'm assuming that showException doesn't rethrow it.)

So if you call the first method and "do something" fails, then the caller will have to handle the exception. If you call the second method and "do something" fails, then the caller won't see an exception at all... which is generally a bad thing, unless showException has genuinely handled the exception, fixed whatever was wrong, and generally made sure that calculateArea has achieved its purpose.

You'll be able to tell this, because you can't call the first method without either catching Exception yourself or declaring that your method might throw it too.

Yes. The version which declares throws Exception will require the calling code to handle the exception, while the version which explicitly handles it will not.

i.e., simply:

performCalculation();

vs. moving the burden of handling the exception to the caller:

try {
performCalculation();
catch (Exception e) {
// handle exception
}

They differ in where the responsibility to deal with the Exception lies. First one just throws Exception, so it does not handle it. The code that calls the method needs to handle the Exception. Second one catches and handles the Exception within the method, so in this case the caller doesn't have to do any exception handling, provided showException() itself does not throw another exception.

Yes, there is a great deal of difference between them. The in the first code block, you pass the exception to the calling code. In the second code block you handle it yourself. Which method is correct depends entirely on what you are doing. In some instances, you want your code to handle the exception (if a file isn't found and you want to create it, for instance) but in others, you want the calling code to handle the exception (a file isn't found and they need to specify a new one or create it).

Generally speaking as well, you don't want to catch a generic exception. Instead, you'll want to catch only specific ones, such as FileNotFoundException or IOException because they can mean different things.

I assume that by "identical" you are referring to behavior.

A behavior of a function can be determined by:

1) Returned value

2) Thrown exceptions

3) Side effects (i.e changes in the heap, file system etc)

In this case, the first method propagates any exception, while the second throws no checked exception, and swallows most of the unchecked exceptions as well, so the behavior IS different.

However, if you guarantee that "do something" never throws an exception, then the behavior would be identical (though the compiler will require the caller to handle the exception, in the first version)

--edit--

From the point of view of API design, the methods are completely different in their contract. Also, throwing class Exception is not recommended. Try throwing something more specific to allow the caller to handle the exception better.

There is one particular scenario where we cannot use throws, we have got to use try-catch. There is a rule "An overridden method cannot throw any extra exception other than what its parent class is throwing". If there is any extra exception that should be handled using try-catch. Consider this code snippet. There is a simple base class

package trycatchvsthrows;


public class Base {
public void show()
{
System.out.println("hello from base");
}
}

and it's derived class:

package trycatchvsthrows;


public class Derived extends Base {


@Override
public void show()   {
// TODO Auto-generated method stub
super.show();


Thread thread= new Thread();
thread.start();
try {
thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


// thread.sleep(10);
// here we can not use public void show() throws InterruptedException
// not allowed
}
}

When we have to call thread.sleep() we are forced to use try-catch, here we can not use:

 public void show() throws InterruptedException

because overridden method can not throw extra exceptions.

The caller of this method will need to either catch this exception or declare it to be rethrown in it's method signature.

private void calculateArea() throws Exception {
// Do something
}

In the try-catch block example below. The caller of this method doesn't have to worry about handling the exception as it has already been taken care of.

private void calculateArea() {
try {
// Do something


} catch (Exception e) {
showException(e);
}
}

Many times you want the caller to handle the exception. Let's say you have the caller call a method which calls another method which calls another method, instead of having each method handle the exception, you can just handle it at the caller. Unless, you want to do something in one of the methods when that method fails.

If you threw an exception, the child method (which overrides this) should handle the exception

example:

class A{
public void myMethod() throws Exception{
//do something
}
}


A a=new A();
try{
a.myMethod();
}catch Exception(e){
//handle the exception
}
private void calculateArea() throws Exception {
....do something
}

This throws the exception,so the caller is responsible for handling that exception but if caller does not handle the exception then may be it will given to jvm which may result in abnormal termination of programe.

Whereas in second case:

private void calculateArea() {
try {
....do something
} catch (Exception e) {
showException(e);
}
}

Here the exception is handled by the callee,so there is no chance of abnormal termination of the program.

Try-catch is the recommended approach.

IMO,

  • Throws keyword mostly used with Checked exceptions to convince compiler but it does not guarantees normal termination of program.

  • Throws keyword delegate the responsibility of exception handling to
    the caller(JVM or another method).

  • Throws keyword is required for checked exceptions only ,for unchecked exceptions there is no use of throws keyword.