views:

1217

answers:

11

Hello,

I have a question about throwing exceptions in Java, a kind of misunderstanding from my side, as it seems, which I would like to clarify for myself.

I have been reading that the two basic ways of handling exception code are:

1.) throwing an exception in a try-block with "throw new ...", and catching it immediately in a catch-block - the so called try-throw-catch mechanism.

2.) throwing an exception in a method with "throw new ..." and then declaring in the header of the method that this method might throw an exception with "throws ..." - the so called pass-the-buck.

I have recently read that "it doesn't make any sense to throw an exception and then catch it in the same method", which made me think whether I understand the thing in the wrong way, or the person who had written this had something else in mind. Doesn't the first way of handling exceptions does exactly this (the try-throw-catch mechanism) ? I mean, it throws an exception and catches it in the same method. I have read that it is a better practice to throw an exception in one method, and catch it in another method, but this is just one (probably better) way. The other way is also legal and correct, isn't it?

Would you, please, give me a comment on this ? Thank you very much.

+6  A: 

I think you misunderstood the first case. Normally you add a try-catch-block when you call some method which may throw exceptions. Catching locally thrown exceptions indeed doesn't make much sense. In particular you shouldn't use exceptions to exit from loops, as this is extremely slow compared to a standard approach.

starblue
+2  A: 

With the first way do you mean something like this:

try {
  ok = doSomething();
  if (!ok) {
   throw new Exception("Error");
  }
 ok = doSomethingElse();
}catch (Exception e) {
}

This will allow you to exit the try-catch block without executing the rest of it. This is the only valid usage I can think of throwing an exception with throw and catching it yourself in a try-catch block. However, standard if blocks should be used instead. I don't understand why someone should throw an exception and then catch it himself.

The second way is more standard, especially if the caller of the method that throws an exception is an external module. This is a way of signaling that something real wrong happened. It is the responsibility of the caller to handle the exception.

kgiannakakis
What's the point of the 'ok' variable in this code? You need EITHER the exception OR the ok flag.
DJClayworth
I imagine that it's just for clarity in this simple example.
Calum
Sorry, please ignore the above comment. I'm having that Monday morning feeling.
DJClayworth
+1  A: 

My expierence is that using the first method gets your code quickly unreadable - since the functionality and the error-handling is getting mixed up. BUT it makes sense in some cases where you have a try{}catch{}finaly{} - for example in file handling or database handling where you ALLWAYS want the connection to be closed.

try{ //do something
}catch(Exception ex){
//log
}finally{
//connection.close
}

For everything else I use the second option - just for the reason to centralize my error-handling routines and keep the readability of the code implementing the businesslogic itself.

Gambrinus
+13  A: 

Exceptions should be thrown from a method when that method is incapable of resolving the exception on its own.

For example, a FileNotFoundException is thrown from new FileInputStream(new File(filename)) because the FileInputStream itself can't handle a case where a file is missing; that exception needs to get thrown so the end-user application can handle the problem.

There are some cases where exceptions could be handled within a method. For example, a Document model method throwing a BadLocationException could be handled within a sufficiently intelligent method. Depending on the problem, either the exception can be handled or re-thrown.

(Anyway, I'd argue that throwing an exception from within a try-catch block so the catch block can be executed represents really bad logic flow)

David
tiny nitpick: "new File(filename)" doesn't throw an exception when the file doesn't exist.
Joachim Sauer
Oh yeah... thanks! Fixed. :)
David
+1  A: 

In my opinion, try blocks that you write should not include any "throw new" that are caught inside the same method. When you throw an exception, you're saying "I've encountered a situation that I can't handle; somebody else will have to deal with it." Your method with the "throw new" should either create an unchecked exception to throw or declare a checked exception in its method signature.

If you're using 3rd party classes that may throw exceptions, your method should have a try/catch block if you can actually handle the situation if an exception arises. Otherwise, you should defer to another class that can.

I don't create my own exception and then catch it in the same method.

duffymo
+2  A: 

If you're going to manually throw an exception, then obviously you know there has been some error that needs to be handled. Rather than throw the new exception, then catch it, then immediately handle the error, why not just handle the error? You (and the processor) don't need to go through all the work of generating an exception and catching it. The exception also makes the code harder to read and debug.

You would throw an exception, rather than just handling the error immediately, if:

  • Other code, like the code that called your method, should handle the error. For example, if your code is not UI code, then it probably shouldn't generate windows. This is your method #2.

  • You can take advantage of the try, catch, finally block. It's possible that you could write cleaner code this way, but I think that 90% of the time your code would be more readable using simple if statements.

Scott Saunders
+4  A: 

Doesn't the first way of handling exceptions does exactly this (the try-throw-catch mechanism)? I mean, it throws an exception and catches it in the same method.

That's not a "way of handling exceptions" - it's utter nonsense. The whole point of exceptions is to let another method up the call stack handle it. If you're going to handle the condition within the same method, there's no point in using an exception - that's what if() is for! If that makes the control flow of your method too complicated, you should probably refactor some of the logic into separate methods - and then it might make sense to have those throw exception that the remaining method body catches.

That being said, I can imagine one special case where it could make sense to throw and catch an exception in the same method: when you're already calling a method that may throw an exception and have a catch block to handle it, then in some cases it could make sense to throw an exception to indicate a similar problem that the existing catch block can handle in the same way.

Michael Borgwardt
Thank you. I understand better now. However, the Java intro books are full of such simple programs, which use "throw new " in an if-statement, surrounded in a try-catch block. And probably, until you get more experience with writing real programs, you can't understand this the way you explain it.
If the books use it that way, it's to explain how exceptions and exception handling works in small code examples - or the books are simply bad.
Michael Borgwardt
+1  A: 

The person who wrote "it doesn't make any sense to throw an exception and then catch it in the same method" is entitled to their opinion, but it's not widely shared. There are plenty of cases where throwing and catching an exception in the same method is what's needed. The simplest is where you are doing a sequence of operations and the failure of any one of them makes the rest invalid. If you detect that one of these operations fails it's perfectly reasonable to throw an exception and catch it at the end of the method. In fact it's the logical way of doing things. Arguably you could rewrite the code to not use the exception, maybe with some status flags and a break statement or two, but why would you? Using an exception makes it clear what's going on and improves code readability.

DJClayworth
+1  A: 

Hi Gemm,

I'm gonna answer your questions in turn, then add some comments to the end. I'm not an authority on exception handling, but I hope my comments are helpful.


"Doesn't the first way of handling exceptions does exactly this"?

My answer is yes, as you describe it the first method does operate by throwing and catching an exception in the same method. However, I don't know that try-throw-catch has to work as you describe it.


"I have read that it is a better practice to throw an exception in one method, and catch it in another method, but this is just one (probably better) way. The other way is also legal and correct, isn't it?"

I agree that catching exceptions from a second method is better, but the first way is legal. Is it correct? well that's for you to decide, it is your code, after all.

For the most part, I agree that it doesn't make sense to throw an exception then immediately catch that exception in the same method. If we do this because the method is particularly long/complex and handling the error using other logic would complicate things more, then I would suggest moving some of this logic to another method and calling that method and catching its exception.

If our code is simpler, then it may be easy to handle the error using code that doesn't consist of throwing an exception.


My comments:

The try-throw-catch mechanism you mentioned may not need the exception to be thrown in the same method. I would have to read the text you found to be certain, but I would expect that it isn't necessary. If it didn't need the exception to be thrown in the same method, then your exceptions handling strategy is a combination of 1) and 2).

In the combo, one method would use try-throw-catch mechanism to catch an exception thrown by a called method. It seems to me that 1) and 2) should work together to form your exception handling strategy.

Now, maybe someone will come along and give us some wonderful reasons why we might want to throw an exception in the same method. I expect there are some, but to me they seem the exceptions, not the rule.

Cheers, Ed

Ed Gonzalez
A: 

The reason why that would seem as nonsense ( throwing and catching in the same method ) is because that would be an scenario of using exceptions for flow control. If you already have enough data as to identify the condition where the exception should be thrown then you could use that information to use a condition instead.

See below:

1) Throwing and catching exception in same method ( wrong )

public void method() { 
    try {    
        workA...
        workA...
        workA...
        workA...    
        if( conditionIvalid() && notEnoughWhatever()  && isWrongMoment() ) { 
            throw new IllegalStateException("No the rigth time" );
        }
        workB...
        workB...
        workB...
        workB...
    } catch( IllegalStateException iee ) { 
        System.out.println( "Skiped workB...");
    }
    workC....
    workC....
    workC....
    workC....
}

In this scenario the exception throwing are used to skip the section "workB".

This would be better done like this:

2) Using condition to control flow ( right )

public void method() { 
    workA...
    workA...
    workA...
    workA...    
    if( !(conditionIvalid() && notEnoughWhatever()  && isWrongMoment() ) ) { 
        //throw new IllegalStateException("No the rigth time" );
        workB...
        workB...
        workB...
        workB...

    }
    workC....
    workC....
    workC....
    workC....
}

And then you can refactor the condition:

    if( !(conditionIvalid() && notEnoughWhatever()  && isWrongMoment() ) ) {

for

    if( canProceedWithWorkB() ) {

implemented as:

  boolean canProceedWithWorkB() {  
      return !(conditionIvalid() && notEnoughWhatever()  && isWrongMoment() );
  }
OscarRyz
A: 

Using an exception for control flow is specifically dealt with in Effective Java, 2nd Edition by Joshua Bloch, Item 57:

Item 57: Use exceptions only for exceptional conditions

...exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow. [italics mine]

So while it certainly "works" to use exceptions to control flow, it is not recommended.

Jeff Olson