3

I've been trying to create a general trycatch method like this:

public static void tryCatchAndLog(Runnable tryThis) {
    try {
        tryThis.run();
    } catch (Throwable throwable) {
        Log.Write(throwable);
    }
}

However I get an unhandled exception if I try to use it like this:

tryCatchAndLog(() -> {
    methodThatThrowsException();
});

How can I implement this so that the compiler knows that tryCatchAndLog will handle the Exception?

DimaSan
  • 12,264
  • 11
  • 65
  • 75
EJS
  • 1,011
  • 5
  • 14
  • 28

2 Answers2

5

Try this :

@FunctionalInterface
interface RunnableWithEx {

    void run() throws Throwable;
}

public static void tryCatchAndLog(final RunnableWithEx tryThis) {
    try {
        tryThis.run();
    } catch (final Throwable throwable) {
        throwable.printStackTrace();
    }
}

Then this code compiles:

public void t() {
    tryCatchAndLog(() -> {
        throw new NullPointerException();
    });

    tryCatchAndLog(this::throwX);

}

public void throwX() throws Exception {
    throw new Exception();
}
Sxilderik
  • 796
  • 6
  • 20
  • 2
    I would advise against catching `Throwable` though; catch `Exception` unless you have a good reason not to do so. – Sxilderik Dec 23 '16 at 11:31
4

Change Runnable to custom interface that is declared to throw Exception:

public class Example {

    @FunctionalInterface
    interface CheckedRunnable {
        void run() throws Exception;
    }

    public static void main(String[] args) {
        tryCatchAndLog(() -> methodThatThrowsException());
        // or using method reference
        tryCatchAndLog(Example::methodThatThrowsException);
    }

    public static void methodThatThrowsException() throws Exception {
        throw new Exception();
    }

    public static void tryCatchAndLog(CheckedRunnable codeBlock){
        try {
            codeBlock.run();
        } catch (Exception e) {
            Log.Write(e);
        }
    }

}
Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96