1

Question: How to do both: handle exception in outer method and return result of inner method?

I have: two methods which return List:

import java.util.List;
import java.util.LinkedList;

public class HelloWorld {

     public static void main(String[] args){
        System.out.println("Result = " + new HelloWorld().parseWrapper()); 
     }

     public List<Integer> inner() {
         List<Integer> list = new LinkedList<Integer>();
         for (int i = 0; i < 5; i++) {
             if (i % 4 == 0) throw new RuntimeException();
             list.add(i);
         }
         return list;
     }

     public List<Integer> outer() {
         List<Integer> list = null;
         try {
             list = parse();
         } catch (Exception e) {
             System.out.println("Handle exception!");
         } finally {
             return list;
         }
     }
}

Result:

Handle exception!
Result = null // PROBLEM: I DON'T WANT TO LOOSE IT

Problem: I loose result list. I want both: to handle exception and to return [1, 2, 3] list from outer method.

VB_
  • 45,112
  • 42
  • 145
  • 293
  • 3
    Create a `Result` object hat has a `list` and an `exception`. Return that. – Sotirios Delimanolis Jun 24 '14 at 17:44
  • `new HelloWorld().parseWrapper()` and `parse()` in method `outer` are both syntax errors. Should we assume that `outer` and `inner` were originally called `parseWrapper` and `parse`? – David Conrad Jun 24 '14 at 18:20
  • BTW, returning from a `finally` block is generally considered a bad thing: http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java – David Conrad Jun 24 '14 at 18:23
  • Also, the list would be empty, it wouldn't contain [1, 2, 3], since the exception would be thrown on the first iteration of the loop, before anything had been added to the list. – David Conrad Jun 24 '14 at 18:26

2 Answers2

6

No - the inner method doesn't return anything, because it throws an exception instead. The outer method simply doesn't have a result to work with.

If a method throws an exception, it's generally expected that none of the work in the method is useful.

If you want to populate a list as far as you can, you could pass the list into the method instead:

public void inner(List<Integer> list) {
    for (int i = 0; i < 5; i++) {
        if (i % 4 == 0) throw new RuntimeException();
        list.add(i);
    }
}

Then call it as:

public List<Integer> outer() {
    List<Integer> list = new LinkedList<>;
    try {
        parse(list);
    } catch (Exception e) {
        System.out.println("Handle exception!");
    } finally {
        return list;
    }
}

It's rarely a good idea, to be honest - in my experience, most exceptions can't really be handled and resumed; it's more a case of "work out what needs to be cleaned up, and the unit of work to abort". That's not universally true of course, but what you're trying to achieve in terms of partial results from a method is pretty rarely useful.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

You could just bring your list instanciation at the class level:

public class HelloWorld {
    private List<Integer> list = new LinkedList<>();

    public List<Integer> inner() {         
      for (int i = 0; i < 5; i++) {
         if (i % 4 == 0) throw new RuntimeException();
         list.add(i);
      }
      return list;
    }

    public List<Integer> outer() {
        try {
            parse();
        } catch (Exception e) {
            System.out.println("Handle exception!");
        } finally {
            return list;
        }
    }
}

Just be careful with multiple accesses to the same instance of your class, as you will be messing with same list instance in each call.

But still I'm wondering the real reason of throwing an exception there instead of just returning the partial list:

if (i % 4 == 0) return list;
Mathieu Fortin
  • 1,048
  • 7
  • 17