2

I have a lot of code with try/catch and in almost all cases I take the same action. What I want to do is simplify my error handling by creating something where I can just say

ManagedExceptionEnvironment() {
    // The code that might throw exceptions
}

And then inside of ManagedExceptionEnvironment it has the shared error handling logic.

My initial thought on this was to have ManagedExceptionEnvironment's constructor take a Runnable, but if you put logic that might throw an exception inside an anonymous Runnable's run method then it still complains about not implementing try/catch even if the container you're passing it to would have taken care of it.

I suppose another option is to only handle the errors at the highest level and have them keep getting thrown up another level, though that seems rather risky.

Edit: I guess one option here (and I don't know if this is a thing in Java) is some kind of macro?

Edit 2: Just did some cursory reading on using the C pre-processor to inject macros into Java src and that is really horrifying. So macros are out as a solution.

Nick Chapman
  • 4,402
  • 1
  • 27
  • 41
  • Lambda expressions are available for [every version of Android](https://developer.android.com/studio/write/java8-support). – CommonsWare Aug 18 '18 at 17:23
  • @CommonsWare so to get this straight, all versions of android support lambdas but not all other features of Java 8? – Nick Chapman Aug 18 '18 at 17:28
  • It's a mixed bag. The big thing is that Java 8 *classes* are not available prior to API Level 24. Lambda expressions do not involve Java 8 classes. The Android toolchain generates compiled code for lambda expressions that can run on any version of Android. – CommonsWare Aug 18 '18 at 17:34

3 Answers3

4

Unless ManagedExceptionEnvironment was going to extend some existing class, there is no value in using a Java class here as opposed to a static method. So, you could write:

public static <T> T boomProtector(Callable<T> thingThatMightGoBoom) {
  try {
    return thingThatMightGoBoom.call();
  }
  catch(Exception e) {
    // TODO: your standard catch logic
  }

  return null;
}

Then, where you need it, you can call:

Whatever result = boomProtector(() -> earthShatteringKaboom());

where Whatever is the type that earthShatteringKaboom() returns. If earthShatteringKaboom() returns an object, you get it in result. If it throws an exception, your standard catch logic is executed and result is null.

(note: I am showing Java 8 syntax for the sample boomProtector() call, which you will need to enable in your project, such as via File > Project Settings > app in Android Studio — or, use an anonymous inner class implementation of Callable<T>)

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
2

How about wrapping it in an interface like this:

class ManagedExceptionEnvironment {
    public static void safeExecution(Wrapper w) {
        try {
            w.codeThatThrows();
        } catch (Exception e) {
            // your error handling
        }
    }


    public static void example() {
        safeExecution(() -> { throw new Exception(); });
        // Or the old-fashioned way:
        safeExecution(new Wrapper() {
            @Override
            public void codeThatThrows() throws Exception {
                throw new Exception();
            }
        });
    }

    interface Wrapper {
        public void codeThatThrows() throws Exception;
    }
}

The trick is that the method that is analogous to Runnable.run() specifies that it may throw an Exception whereas run() does not.

Janus Varmarken
  • 2,306
  • 3
  • 20
  • 42
1

You can make exceptions part of the (generic) signature of your interface / class / method. See my question ( How to not throw a generically specified exception? ) as example.

Instead of calling the method "newInstance()" you could name it "process()" for example. And then create a type safe handler around that. And clients simply pass lambda expressions around.

Basically defining your own wrapper (as shown in the other answer :-)

GhostCat
  • 137,827
  • 25
  • 176
  • 248