What is the best way to force a try block to break in between?
Asked Answered
F

10

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.

Fransis answered 6/1, 2012 at 18:28 Comment(22)
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.Gebler
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.Barman
At the very least throw an exception manually instead of doing a divide-by-zero.Illfated
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!Fransis
Another thing, I'm doing this on a blacberry device.Fransis
@Fransis 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?Burden
Why can't you just use a return statement if you don't want to do anything?Ronda
@Burden It wasn't being used anyway, so...Fransis
@srikanthradix I can't use return in the middle of the block.Fransis
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.Sedition
@Fransis see my answer. Move the code from inside the try block to it's own method, and then you can use return.Gallager
@Fransis 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.Burden
@Burden 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 :)Fransis
@SLaks Hmmm...very convincing!!! Now, would you mind moving to the "why" part?Fransis
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.Irra
@Irra 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!Fransis
Exceptions have overhead at runtime. It also results in less-readable code, and it can be annoying when debugging.Irra
@Irra 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?Fransis
@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).Irra
@Irra By "throwing an exception manually", I meant "throw new Exception("Ugly GOTO hack")". Anyway, came across this link... clearly, the overhead caused by stack trace is the primary deterrent and the best way is to use breakFransis
@tipycalFlow: All exceptions (except division by 0 and null ref) are thrown that way.Irra
@Irra 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 :)Fransis
C
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]

Crumpler answered 6/1, 2012 at 18:32 Comment(7)
@Max Not in javaGebler
@pst Whoops, didn't see you linked.Androclinium
goto is a reserved word but its not used in javaAlleged
@pst the break label in your link can be used as a replacement even with plain blocks.Huron
-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.Gallager
+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...Fransis
@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.Crumpler
A
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.

Anora answered 6/1, 2012 at 18:38 Comment(5)
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.Sedition
-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.Gallager
@user949300: agreed, it's terrible advice but still marginally better than his own sample. What do you suggest?Anora
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)Gallager
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 booleans to differentiate between the exceptions and handle them accordingly.Fransis
C
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]

Crumpler answered 6/1, 2012 at 18:32 Comment(7)
@Max Not in javaGebler
@pst Whoops, didn't see you linked.Androclinium
goto is a reserved word but its not used in javaAlleged
@pst the break label in your link can be used as a replacement even with plain blocks.Huron
-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.Gallager
+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...Fransis
@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.Crumpler
G
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...
Gallager answered 6/1, 2012 at 18:52 Comment(0)
S
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.

Sedition answered 6/1, 2012 at 19:3 Comment(0)
T
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;
}
Thorlie answered 6/1, 2012 at 19:13 Comment(0)
B
0

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

//--do stuff----
if (!shouldStop) {
    // continue doing stuff
}
Barbitone answered 6/1, 2012 at 18:33 Comment(0)
J
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)

Jessjessa answered 6/1, 2012 at 18:37 Comment(0)
H
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.

Huron answered 6/1, 2012 at 18:46 Comment(0)
D
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.
}
Dogeatdog answered 6/1, 2012 at 19:47 Comment(0)
G
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
Gifu answered 11/9, 2013 at 7:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.