views:

207

answers:

4

Basically iterating through a list and,
- Invoke method on first object
- Catch first exception (if any); if there are no more exceptions to catch, return normally. Otherwise, keep on invoking method until all exceptions are caught.
- Move on to next object.

I can iterate through each object, invoke the method, and catch one exception but I do not know how to continuously invoke the method on it and keep on catching exceptions :S

Thanks :)

+1  A: 

If you're talking about dealing with a single method call that will throw more than one exception, it can't be done -- no matter how many times you call the method, it will keep on throwing the first exception. You can't go back into the method and keep running from there; after throwing one exception, it's all over.

But if you're talking about a method that sometimes throws exceptions and sometimes doesn't, try something like this:

boolean thrown = false;
do {
    try {
        thrown = false;
        method();
    }
    catch (Exception e) {
        thrown = true;
        // Handle as you like
    }
} (while thrown);
Etaoin
"no matter how many times you call the method, it will keep on throwing the first exception" - trivial counterexample: `class Ex { int counter = 5; void throwFive() throws Exception { if (counter--) { throw new Exception("boo"); } } }`
Péter Török
For something like that, see my second case. See earlier in the sentence you quoted: "If you're talking about dealing with a single method call that will throw more than one exception." For example, `void foo() throws Exception {throw new Exception("one"); throw new Exception("two");}` in which case there's no way to catch the second exception because it is never thrown.
Etaoin
Ah I see now what you meant. And it is indeed right. Sorry for the misunderstanding.
Péter Török
+3  A: 

This is similar to the other answers, but without the flag, which seems like clutter to me. I don't really understand the question though, so I'm just throwing it out there in case it is useful.

for (Item item : items) {
  while (true) {
    try {
      item.doSomething();
      break;
    } catch (MyException ex) {
      log.warn("Something failed.", ignore);
    }
  }
}

This approach hinges on the operation of the unlabeled break statement, which completes abruptly and then exits the enclosing while statement normally.


Based on subsequent comments, I think there is some confusion about what it means when there are multiple exceptions declared to be thrown by a method.

Each invocation of a method can be terminated by just one exception being thrown. You can't somehow resume invocation where it left off, and handle subsequent exceptions.

So, if a method throws multiple exceptions, catch a common ancestor, and move on. For example, if a method throws java.io.EOFException or java.nio.channels.ClosedChannelException, you could simply catch java.io.IOException since it is a common ancestor. (You could also catch java.lang.Exception or java.lang.Throwable for the same reason.) Invoking the method again under the same conditions won't get you any further.

If you want to attempt to invoke the method on each object, even if some fail, use this:

for (Item item : items) {
  try {
    item.doSomething();
  } catch (Exception ignore) { /* This could be any common ancestor. */
    log.warn("Something failed.", ex);
  }
}
erickson
A: 

I'm assuming that you are trying to performs some kind of validation to the items in a list, where the validation errors are reported by throwing exceptions. I'm also assuming that you are trying to collect all of the validation errors.

The simple answer is that this problem cannot be solved using this approach. To understand why, take a look at this:

boolean exceptionCaught = false;
do {
    try {
        item.doSomething();
    } catch (MyException e) {
        exceptionCaught = true;
    }
} while (exceptionCaught);

This fails because each time you call item.doSomething() it is going to throw an exception at exactly the same place. The net result is an infinite loop.

The best you can do with this approach is to capture the first exception for each item in the list.

So how can you achieve what you are trying to achieve? The answer is that you have to change the validation code to use some other way to report errors than throwing exceptions. For example, you could change:

class Item {
    ...
    void validate() {
        if (noHat) {
            throw new MyException("bad hat");
        }
        if (noPants) {
            throw new MyException("world-wide pants");
        }
    }
}

to something like this:

class Item {
    ...
    void isValid(List<MyException> errors) {
        boolean ok = true;
        if (noHat) {
            errors.add(new MyException("bad hat"));
            ok = false;
        }
        if (noPants) {
            errors.add(new MyException("world-wide pants"));
            ok = false;
        }
        return ok;
    }
}

Messy huh! You could sugar this in various ways, but this style of error reporting is always going to be more complicated. But I don't think there is a practical way to avoid the messiness AND capture ALL of the validation errors.

Stephen C
A: 

This is what I understand.

You have an object's method which may throw a number of exceptions.

What you want to do is to catch them all and continue with the next object in the list.

Is that correct?

So, that would be:

for( YourObject o : yourList ) {
    try {
       o.thatMethod();//invoke that risky method 
    } catch( SomeExceptionClass sec ) {
       // Do something with that exception
    } catch( SomeOtherExceptionClass soec ) {
       // Do something with that exception  
    } catch( YetAnotherxceptionClass yaec ) {
       // Do something with that exception
    } catch( OtherUnRelatedException oue ) {
       // Do something with that exception
    }
}

When you do this, if the invocation of thatMethod() throws an exception and that exception is listed in the catch section, the execution flow will jump to that exception and after it will continue to the normal flow ( which is the for loop and will continue with the next object )

I hope this is what to need. For more information read: The catch block in the Java Tutorial section Essential classes

OscarRyz