6

I have a try-catch block that I wish to break like a switch block but I couldn't find a recommended way of doing it. I'm fetching a lot of data in the try-catch block and wish to stop the fetching in between in case a certain condition is met. Just to get it working for now, I've deliberately forced the code to go into the catch block:

int i=0;
    try {
        //--do stuff----
        if(//-------is condition met?--------//)
            i = 1/0; // divide 1 by 0 -- a definite exception
    }
    catch (Exception e) {//---------do nothing---------//}

Is it safe to do this or should I go for another way?

EDIT:I'm fetching some xml data(actually, a lot). Depending on the internet connection, I need to stop the parsing after sometime(time-out) rather than go through the entire stream. I go through loops but I also make some calculations later. It doesn't make any sense to calculate with incomplete data, so I would prefer to just skip the whole thing.

tipycalFlow
  • 7,594
  • 4
  • 34
  • 45
  • 5
    That's an awful way: can you post a fuller context? A slightly less-bad way is to use a "dummy" loop and break that, which is a silly C-idiom, but I suspect there might be a better way to structure the code entirely. –  Jan 06 '12 at 18:29
  • I agree with @pst; without seeing a bigger example (specifically, what is it that you're trying to skip?), it's difficult to answer this meaningfully. – Oliver Charlesworth Jan 06 '12 at 18:32
  • 1
    At the *very least* throw an exception manually instead of doing a divide-by-zero. – Herms Jan 06 '12 at 18:34
  • It seems throwing an exception manually was the way to go. Also, could anyone point out why doing (1/0) is not recommended - I'm not that good with the basics! – tipycalFlow Jan 06 '12 at 18:59
  • Another thing, I'm doing this on a blacberry device. – tipycalFlow Jan 06 '12 at 19:09
  • @tipycalFlow You definitely don't want to catch `Exception` -- what happens if the code in the `try` unintentionally throws an exception that you mistakenly interpret as your control flow? – yshavit Jan 06 '12 at 19:12
  • Why can't you just use a `return` statement if you don't want to do anything? –  Jan 06 '12 at 19:16
  • @yshavit It wasn't being used anyway, so... – tipycalFlow Jan 06 '12 at 19:21
  • @srikanthradix I can't use `return` in the middle of the block. – tipycalFlow Jan 06 '12 at 19:26
  • 2
    Throwing an exception should only be done in exceptional cases, not the regular case. You should do everything you can to avoid throwing an exception as part of regular program flow. And to answer your question, doing an intentional divide by 0 is simply a very unusual way to accomplish what you want and is likely to mystify (or bemuse) other developers. – Trevor Freeman Jan 06 '12 at 19:37
  • 1
    @tipycalFlow see my answer. Move the code from inside the try block to it's own method, and then you can use return. – user949300 Jan 06 '12 at 20:47
  • @tipycalFlow What do you mean it wasn't being used? The point is, you may be swallowing up (and ignoring) an actual exception that you shouldn't be. – yshavit Jan 06 '12 at 22:34
  • @yshavit You're right...I'm not handling the exceptions right now but the way I see it, an error in parsing and a time-out will be intended to lead to the same result- an error message to the user! So it still makes sense to continue this way :) – tipycalFlow Jan 07 '12 at 06:09
  • @SLaks Hmmm...very convincing!!! Now, would you mind moving to the "why" part? – tipycalFlow Jan 21 '12 at 05:11
  • If you really want to throw an exception, do it explicitly: `throw new Exception("Ugly GOTO hack")`. However, using exceptions for control flow is a bad idea. – SLaks Jan 22 '12 at 02:54
  • @SLaks That's precisely what I wanted to know man... why is using exceptions for control flow a bad idea? I mean, there might be some memory/compiler issue or something else, but what?? I agree such a control flow sounds wrong/unnatural but that is no justification! – tipycalFlow Jan 23 '12 at 08:16
  • Exceptions have overhead at runtime. It also results in less-readable code, and it can be annoying when debugging. – SLaks Jan 23 '12 at 16:27
  • @SLaks hmm...makes sense. Is this also the case when manually throwing exceptions? I think throwing an exception manually should ideally not have any overhead and should be equivalent to a `break` statement, right? – tipycalFlow Jan 23 '12 at 18:39
  • @tipycalFlow: Wrong. There is no such thing as "throwing an exception manually"; all exceptions are thrown somewhere. The slow part is the stack walk (including `finally` stuff). – SLaks Jan 23 '12 at 19:23
  • @SLaks By "throwing an exception manually", I meant `"throw new Exception("Ugly GOTO hack")"`. Anyway, came across [this link](http://www.velocityreviews.com/forums/t518658-exceptions-no-longer-incur-overhead.html)... clearly, the overhead caused by stack trace is the primary deterrent and the best way is to use `break` – tipycalFlow Jan 24 '12 at 05:53
  • @tipycalFlow: All exceptions (except division by 0 and null ref) are thrown that way. – SLaks Jan 24 '12 at 05:53
  • @SLaks You should've put the stack trace overhead part as an answer because this was exactly the reason I was looking for in the question. The overhead is in milliseconds, so is unnoticeable to the layman. So if one doesn't know it, one won't ever know it...atleast not nowadays :) – tipycalFlow Jan 24 '12 at 05:56

10 Answers10

11

This code smells of some anti-pattern but without more context we can't prescribe a better design. In general, you should only throw an exception for a truly exceptional condition in the state of your program. You should especially not throw an exception for normal (expected) control flow, instead you should use control flow statements such as loops (using break/continue) and return.

If you do wish to keep this structure (even though you should not) then I suggest explicitly throwing a special exception class to make it clear what you are doing, e.g.:

public static class ConditionMetException extends Exception { }

// ...
try {
  // do stuff
  if ( /* Is condition met? */ ) {
    throw new ConditionMetException();
  }
} catch (ConditionMetException cme) { /* Do nothing. */ }

But again, you're likely better off refactoring to use a loop and the built in break command.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • The ironic name of the exception should be enough to indicate that this is a really bad idea to implement. I do not mean that as a criticism of the answer (which answers what was asked for in a clean way by making a specific exception for it), but of the idea in general. This should pretty much never be encouraged. – Trevor Freeman Jan 06 '12 at 19:44
  • -1 Maybe I'm in a surly mood today, but I can't believe that a suggestion to throw a "ConditionMetException" for something that is not exceptional and is being used for normal program flow control has 5 upvotes. – user949300 Jan 06 '12 at 20:25
  • @user949300: agreed, it's terrible advice but still marginally better than his own sample. What do you suggest? – maerics Jan 06 '12 at 20:34
  • My answer (scroll around to find it) was to put the code from inside the try block into it's own method, and he can simply `return` from that method when he is done reading. Much more Java idiomatic that a goto, named break, or dubious Exception. (yes, purists could argue that lots of returns aren't all that wonderful either, but it beats the alternatives) – user949300 Jan 06 '12 at 20:45
  • My problem is that the client requires a time-out. And I still don't see a case which would interfere with the intended behavior. The intention was to have a `goto`-like behavior which a `throw` does for me equally well. So far, I don't even need extra `boolean`s to differentiate between the exceptions and handle them accordingly. – tipycalFlow Jan 07 '12 at 06:26
5

Either break or throw will do what you want (and the throw would be preferable, you at least have some traceability as to WTH you're doing.

[edit]

what: try {
         System.out.println ("before break");
         break what;

      } catch (Exception e) {}
   }

[/edit]

KevinDTimm
  • 14,226
  • 3
  • 42
  • 60
  • @Max [Not in java](http://stackoverflow.com/questions/2545103/is-there-a-goto-statement-in-java) –  Jan 06 '12 at 18:36
  • @pst Whoops, didn't see you linked. – Max Jan 06 '12 at 18:42
  • 1
    goto is a reserved word but its not used in java – Sleiman Jneidi Jan 06 '12 at 18:45
  • @pst the break label in your link can be used as a replacement even with plain blocks. – josefx Jan 06 '12 at 18:49
  • -1 (sorry) break only works if you are in a loop/switch, and it's not clear that the code is in a loop. And if it is in a loop (hard to tell from the original post, I sympathize with you there!) you may not end up where you want on the break. – user949300 Jan 06 '12 at 19:09
  • +1, I liked the `break` usage - wasn't aware of this way! Thanks...Anyway, I didn't get why manually throwing an exception got so much criticism here just because it's not "expected"! Code maintenance should also not be an issue, since everyone here immediately understood what it was supposed to do and a little comment would pretty much clear any doubts whatsoever! As for why, I was expecting something like a compiler or memory issue... – tipycalFlow Jan 07 '12 at 08:35
  • @Xerus - then you're doing something wrong, I just wrote a snippet (after 5 years) that works perfectly. Post your code (in a new thread) and ask why it doesn't work. – KevinDTimm Dec 01 '17 at 17:33
1

Throwing an Exception just to break is bad practice.

Would this work for your situation?

  1. Put the code currently inside the try into another method, fetchLotsOfData(). It can still throw IOException or whatever is appropriate.
  2. When you want to stop doing your thing fetching the data, just return. Perhaps returning some true/false or status for the success.

So your final code is something like

int recordsRead = -1;  // -1 means failure
try {
  recordsRead = fetchLotsOfData();
}
catch (IOException ioe) {
  // handle the exception
}

// process what you got...
user949300
  • 15,364
  • 7
  • 35
  • 66
1

It is not the try-catch that you should worry about breaking out of. From what I can tell, you are looking to do something along the lines of:

try
{
  // do thing 1

  // do thing 2

  if (!done)
  {
    // do thing 3

    // do thing 4

    if (still not done)
    {
      // do thing 5
    }
  }
} catch (Exception e)
{

}

If that is what you are trying to do, then that is probably how you should do it (instead of trying to escape from the try-catch). The other way is to shrink your try-catch blocks to surround each task individually.

If you provide more context to your question then it may be possible to provide a better answer.

Trevor Freeman
  • 7,112
  • 2
  • 21
  • 40
1

I'm going to answer the "is is a good idea?" part of the question: No.

It is not a good idea to use exceptions to implement expected flow-of-control. It is possible, but not expected, just as it's possible to make all your variables Strings and implement all your data structures in arrays.

Try-blocks are for creating a scope boundary that has certain guarantees at termination (the catch and finally behavior). A code maintainer seeing:

try{ ... }catch(Exception x){} 

would very strongly tend to either rethrow x (perhaps wrapped) or eliminate the block entirely.

Try-blocks are not about what's inside their scope. That's what standard looping constructs and, better, functions are for. Your question simply goes away if you put your scope in a function:

RetVal doStuff(Arg arg){
    //--do stuff----
    if(//-------is condition met?--------//)
        return myResult;
}
Larry OBrien
  • 8,484
  • 1
  • 41
  • 75
0

Just throw whichever exception you want caught...

boolean stopLoop = false;
while (!stopLoop) {
    try {
        int key = Integer.parseInt(userInput);
        if (key > cutOff) throw new NumberFormatException();//<--like this
        else {
            System.out.println("Good job, your number didn't suck");
            //do some stuff...
            stopLoop = true;//<--End loop after some stuff
            //some more stuff, or..
            if(nomorestuff)break;//<--exit loop
        }
    catch (NumberFormatException nfe){
        System.err.println("Enter a number less than "+cutOff);
    }
}//end while
JReyn
  • 99
  • 5
0

Just put the rest of the fetching into an if block with the inverse condition:

//--do stuff----
if (!shouldStop) {
    // continue doing stuff
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

Looking by your code

int i=0;
    try {
        //--do stuff----
        if(//-------is condition met?--------//)
            i = 1/0; // divide 1 by 0 -- a definite exception
    }
    catch (Exception e) {//---------do nothing---------//}

if the condition is not met? then you dont need to worry about using break, and

if the condition is met, there will be definitely an exception, and it is handled in catch(although you are not doing anything)

Rajesh Pantula
  • 10,061
  • 9
  • 43
  • 52
0

If there is no other way you can use a block label

 load:{
      if(test)//skip the remaining load block
         break load;

  }

Otherwise you could refactor the loading code into a different method and return early.

josefx
  • 15,506
  • 6
  • 38
  • 63
0

Do not use exceptions for non-exception error handling. This is likely a named anti-pattern. If so, I don't know the name.

Here is an example of breaking out of a loop when an exception is thrown and not using exception handling to perform non-exception error handling:

try
{
  while (... whatever ...)
  {
    ... do something that might throw a BlammoException.
  }
}
catch (BlammoException exception)
{
  ... handle the exception.
}
DwB
  • 37,124
  • 11
  • 56
  • 82