I'm not sure it's widely appreciated that throws
clauses can take generic parameters, just as return type or arguments. You can leverage this to improve your error handling. Note the helpful type inference provided by the compiler:
public final class ErrorHandlingMain { public static void main(final String... args) { final Result<String, RuntimeException> fooResult = success("foo"); final Result<String, Exception> barResult = failure(new IOException("bar")); // Note #1 out.println(fooResult.get()); // Note #2 out.println(get(fooResult)); // Note #3 try { out.println(barResult.get()); // Note #4 } catch (final Exception e) { out.println(e); } try { out.println(get(barResult)); } catch (final Exception e) { out.println(e); } } public static <T, E extends Exception> T get(final Result<T, E> result) throws E { return result.get(); } @FunctionalInterface public interface Result<T, E extends Exception> { T get() throws E; static <T> Result<T, RuntimeException> success(final T value) { return () -> value; } static <T, E extends Exception> Result<T, E> failure( final E exception) { return () -> { throw exception; }; } } }
(Unusual formatting to help with screen width.)
- Note type widening from
IOException
toException
. Reversing those types won't compile. - Compiler sees
RuntimeException
, does not requiretry
/catch
. - Likewise for static methods.
- Compiler sees
Exception
, requirestry
/catch
.
No comments:
Post a Comment