In my code, I will attempt a certain task in a try-block. If exceptions are thrown, the catch-blocks will rectify the errors encountered (usually prompting for correct input). After that, the program is supposed to try again repeatedly until success is achieved. My current code is as follows:
for (bool isSuccess = false; !isSuccess;) {
try {
...
isSuccess = true;
}
// catch blocks here to correct any exceptions thrown
}
As can be seen, I'm currently using a loop structure to make the try-catch block start over if the try block fail, until the try block succeeds completely. Is there a more elegant solution?
I'd prefer to see a do loop that exits by default (then there is less chance of encountering an infinite loop). Your use of the boolean type only really mimics the behaviour of break and continue. As an alternative, perhaps more natural way, consider
do {
try {
// some code
} catch (/*whatever*/){
continue; // go again
}
break;
} while (true);
Just to give you an alternative, and if your code allows you to do so, then you could also use recursion. But in my eyes this is less favorable compared to the other ways to solve this.
public void doSomething() {
try {
...
} catch(Exception e) {
doSomething();
}
}
You can simple use a while loop.
while(!isSuccess){
try{
//DO Stuff
}
}
I think you should define a maximum of attempts. Otherwise in a worst scenario when all failures occur you app will be frozen.
You can do it with while loop
boolean isSuccess = false;
while(!isSuccess) { // loop till to isSuccess become true
try {
....
isSuccess = true;
} catch (Exception e) {
// Some Exception accrued, you can have 2 options
// 1. break the loop with break;
// 2. continue the process
}
}
You can also use recursion to do this. But I don't think it would be efficient. Do ... while would be the best approach.
Related
In this scenario:
Cursor cursor = dbHandler.fetchEvents();
boolean someBool = true;
do {
someStuff();
variables = things;
otherStuff();
} while (someBool && cursor.moveToNext());
There is a possibility that cursor.moveToNext() could throw a number of exceptions, particularly if my database is closed unexpectedly while I am working with the cursor.
What would be the best way to handle any possible exceptions thrown in the while() evaluation? Currently, the whole thing just crashes. I'd prefer to avoid that. The compiler does not like my efforts to add a try/catch directly into the while() eval, and it's ugly as hell. I'm thinking I need to create a new method that does this:
private boolean moveToNext(cursor) {
boolean result = false;
try {
result = cursor.moveToNext();
} catch (Exception e) {
... error handling ...
}
return result;
}
And then change my eval loop to:
Cursor cursor = dbHandler.fetchEvents();
boolean someBool = true;
do {
someStuff();
variables = things;
otherStuff();
} while (someBool && moveToNext(cursor));
Does anyone have any other suggestions? If so, I'd love to hear them. Thanks!
Put the entire block of code in a try / catch block, and that block should capture when you lose your database connection.
Then you need to reinvestigate the entire block to see what makes sense to clean up, and that will give you the contents of the "catch block" of the try / catch. Once you do that, you'll probably notice further improvements on your real code, which will probably make this example you posted, and the suggestions less relevant as you zero in on what you care about.
This really depends on what you want to happen when you encounter an error. When you get the Exception, should you just skip that iteration of the loop and move on to the next one, or simply stop iterating? Or is the whole loop borked, and you need to tell your user that something went wrong?
If you really care about handling each iteration of the loop separately, then your approach will work fine. Or if you want to just detect whether the entire loop encountered an error or not, then you can wrap the whole thing in a try block:
try {
Cursor cursor = dbHandler.fetchEvents();
boolean someBool = true;
do {
someStuff();
variables = things;
otherStuff();
} while (someBool && cursor.moveToNext());
} catch (Exception e) {
//report to the user that the loop failed
}
You can always move the code in while() to the loop body, no big deal
while(true)
{
...
if( ! someBool )
break;
if( ! cursor.moveNext() )
break;
}
then surround it with whatever code you like.
I am fairly new to using try/catch blocks, so I don't know how exactly to perform this command.
If I catch an error, I would like to wait a period of time(10 seconds or so) then try to run the same line of code to attempt to continue in my try block. My program is written in Java. I have looked at both these pages: Page1, Page2, but neither of them are in Java. I have also looked at this, but they are not solving in the using the catch block. Is this possible to do, and how would I implement this in my catch block instead of just printing the error?
99% of time, you want to re-run a code-block after a try-catch and not the line with exception.
If you need to run from that line, than that is an indication for you to take your code in another method that encapsulates only that code (maybe move the try-catch there too).
What i would advice is something like this:
void method(){
try{
codeline1;
codeline2;
codeline3;
codeline4;
}
catch(Exception ex)
{
restorClassStateBeforeCodeLine1();
method();
}
}
By that snipped i propose to have your entire try-catch in a separate method.
Waiting random intervals is bad practice also. You never know if 10 seconds is right every time or at all.
Another way that I advise against would be:
label: {
try {
...
if (condition)
break label;
...
} catch (Exception e) {
...
}
}
It uses java labels to retry that part. I never tried but the break could be moved in the catch and the label in the try.
I don't think it is possible to return to a certain line in your try-block from inside a catch-block. Because when the throwis executed, the runtime system is going to pop frames from the call stack, looking for an exception handler to match the thrown exception and once the frame is popped from the stack, it's gone. More info about this can be found here
What you can do is call the method that caused the throw from within the catch-block. But that means it is going to execute your method from the beginning, so maybe you want to try to rearrange your code so that this does not cause any other problems. EDIT: The other answer demonstrates exactly what I mean.
This simple program loops through array values, testing each until it finds a value that doesn't generate an exception
public static void main(String[] args) {
int[] array=new int[]{0,0,0,0,5};
for(int i=0; i<array.length;i++) {
try {
System.out.println(10/array[i]);
break;
} catch(Exception e) {
try { Thread.sleep(1000); } catch(Exception ignore){}
}
}
}
while(true){
try{
//actions where some exception can be thrown
break;//executed when no exceptions appeared only
}
catch(YourException e){
Thread.sleep(10_000);
}
}
This cycle will be repeated while you instructions haven't executed. When code in try-block executed succesfully break helps you leave this cycle
Since you are saying that it is only 2 lines of code that you experience the intermittent error with, try something similar to this.
public static void main(String... args)
{
try
{
//Some Logic
//Error throwing logic in method
while(!doLogic())
{
Thread.sleep(1000);//Sleep here or in doLogic catch
}
//Continuing other logic!
}
catch(Exception e)
{
e.printStackTrace();
}
}
static Integer i = null;
public static boolean doLogic()
{
try
{
//Lines that throw error
System.out.println(i.toString());//NPE First run
}
catch (Exception e)
{
i = 1;
return false;
}
return true;
}
I have started working with enhanced for loops due to it's best practices and habilities to work with ArrayLists.
My code basically gets an ArrayList that contains links to songs and parses this list downloading the songs. One of the exceptions thrown is the TimeoutException, whitch normally happens when the server is overloaded or there's an instability with the internet connection.
To clarify:
try
{
for(Track track : album.getTracks())
{
songdown.downloadTrack(track, directorio, formataudio);
}
}
catch (TimeoutException te)
{
System.out.println("Timeout!");
}
track is an ArrayList whitch is parsed one by one by the songdown.downloadTrack function. When a download fails, a TimeoutException is raised, but I don't know how to treat this exception in order to delete the file I have generated and restart the for statement from the same track, so that the download can happen again.
While it's an open question how advisable this would be, you'd be better off with an inner loop that retries until successful. Something like this:
for (Track track : album.getTracks()) {
boolean downloaded = false;
while (!downloaded) {
try {
songdown.downloadTrack(track, directorio, formataudio);
downloaded = true;
} catch (TimeoutException te) { /* delete partially downloaded song etc */ }
}
}
You'd likely want a max # of retries within each iteration of the for loop or some other additional checks to avoid infinite looping.
There are surely many valid approaches.
Here's one possibility:
int failureCount = 0;
while (failureCount < maxFailures) {
try {
parseAndDownload(someList);
break;
}
catch (Exception ex) {
failureCount ++;
}
}
Please go through this first. First thing is that the catch block should start once the try block is done.
You can catch the exception in the catch block, and write the code which you want to get executed, when the exception occurs, which in you case is starting over again, and deleting the half downloaded songs.
Here is a snippet example, I think you can solve your problem by following this way
ArrayList<String> a = new ArrayList<String>();
a.add("a");
a.add("w");
a.add("d");
//Iterator<String> i = a.iterator();
for(String s:a){
try{
if(s.equals("w")){
throw new Exception("Hello");
}else{
System.out.println(s);
}
}catch (Exception e) {
continue;
}
}
In this snippet, I have explicitly throw an Exception, when it is thrown the catch block will execute, there i have used the keyword continue. This keyword is designed to tackle these kind of situation.
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.
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.
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]
Throwing an Exception just to break is bad practice.
Would this work for your situation?
Put the code currently inside the try into another method, fetchLotsOfData(). It can still throw IOException or whatever is appropriate.
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...
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;
}
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.
Just put the rest of the fetching into an if block with the inverse condition:
//--do stuff----
if (!shouldStop) {
// continue doing stuff
}
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)
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.
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.
}
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
Is there a way to detect, from within the finally clause, that an exception is in the process of being thrown?
See the example below:
try {
// code that may or may not throw an exception
} finally {
SomeCleanupFunctionThatThrows();
// if currently executing an exception, exit the program,
// otherwise just let the exception thrown by the function
// above propagate
}
or is ignoring one of the exceptions the only thing you can do?
In C++ it doesn't even let you ignore one of the exceptions and just calls terminate(). Most other languages use the same rules as java.
Set a flag variable, then check for it in the finally clause, like so:
boolean exceptionThrown = true;
try {
mightThrowAnException();
exceptionThrown = false;
} finally {
if (exceptionThrown) {
// Whatever you want to do
}
}
If you find yourself doing this, then you might have a problem with your design. The idea of a "finally" block is that you want something done regardless of how the method exits. Seems to me like you don't need a finally block at all, and should just use the try-catch blocks:
try {
doSomethingDangerous(); // can throw exception
onSuccess();
} catch (Exception ex) {
onFailure();
}
If a function throws and you want to catch the exception, you'll have to wrap the function in a try block, it's the safest way. So in your example:
try {
// ...
} finally {
try {
SomeCleanupFunctionThatThrows();
} catch(Throwable t) { //or catch whatever you want here
// exception handling code, or just ignore it
}
}
Do you mean you want the finally block to act differently depending on whether the try block completed successfully?
If so, you could always do something like:
boolean exceptionThrown = false;
try {
// ...
} catch(Throwable t) {
exceptionThrown = true;
// ...
} finally {
try {
SomeCleanupFunctionThatThrows();
} catch(Throwable t) {
if(exceptionThrown) ...
}
}
That's getting pretty convoluted, though... you might want to think of a way to restructure your code to make doing this unnecessary.
No I do not believe so. The catch block will run to completion before the finally block.
try {
// code that may or may not throw an exception
} catch {
// catch block must exist.
finally {
SomeCleanupFunctionThatThrows();
// this portion is ran after catch block finishes
}
Otherwise you can add a synchronize() object that the exception code will use, that you can check in the finally block, which would help you identify if in a seperate thread you are running an exception.