Checked exceptions within Block<T>

Peter Levart peter.levart at gmail.com
Sat Jan 12 09:05:38 PST 2013


You could wrap checked exceptions into unchecked by just casting. For 
example:

public interface BlockEx<T> extends Block<T> {
     @Override
     default void accept(T t) {
         try {
             acceptEx(t);
         }
         catch (RuntimeException | Error ue) {
             throw ue;
         }
         catch (Exception e) {
             throw new RuntimeException(e.getMessage(), e);
         }
     }

     void acceptEx(T t) throws Exception;
}


// and then ...


         List<String> strings = ...
         Appendable a = ...

         strings.forEach((BlockEx<String>) s -> {
             a.append(s);
         });


Regards, Peter

On 01/12/2013 05:03 PM, Zhong Yu wrote:
> I too have this problem, since we have lots of code throwing checked
> exceptions, it's a challenge to wrap them in functional interfaces
> that do not throw.
>
> If the solution is to smuggle checked exception as unchecked, JDK
> should provide a standard class for that specific purpose, or
> everybody will be forced to invent their own.
>
> A better solution is probably having varying exceptions
>
>      interface Block<T, E extends Throwable>
>          void apply(T input) throws E;
>
>      <T,E extends Throwable> void forEach(Block<T,E> block) throws E
>
> this is very ugly though; I'd dream the language could make it simpler like
>
>      interface Block<T>
>          void apply(T input) throws ?;
>          // abstract method; throws E; add E to interface.
>
>      <T> void forEach(Block<T> block) throws ? { ... }
>      // non-abstract method; throws E; add E to method.
>
>
> Zhong Yu
>
> On Fri, Jan 11, 2013 at 10:12 PM, Michael Hixson
> <michael.hixson at gmail.com> wrote:
>> This is a bit of feedback for the lambda snapshots.  It's not really
>> suggesting any changes or reporting bugs, but rather describing
>> difficulties I had.  Hopefully this is the right mailing list for this
>> sort of thing.
>>
>> --------------------------------
>>
>> An issue that came up repeatedly was that I wanted refactor code like this:
>>
>>    for (Value value : values) {
>>      ...
>>    }
>>
>> Into this:
>>
>>    values.forEach(value -> {
>>      ...
>>    });
>>
>> But I couldn't because the "..." could throw a checked exception.  I
>> worked around this in two ways:
>>
>>    (a) Don't refactor the code.
>>    (b) Change whatever is throwing the checked exception to throw a
>> runtime exception instead.
>>
>> Option (a) was not so bad if my "values" object was an Iterable.  It
>> was worse when my values were a Map, a Stream, or an Optional.  To
>> compare:
>>
>>    for (Map.Entry<Key, Value> entry : values.entrySet()) {
>>      Key key = entry.getKey();
>>      Value value = entry.getValue();
>>      ...
>>    }
>>
>>    values.forEach((key, value) -> {
>>      ...
>>    });
>>
>>    for (Iterator iterator =
>> values.stream().filter(predicate).map(function).iterator();
>>         iterator.hasNext();) {
>>      Value value = iterator.next();
>>      ...
>>    }
>>
>>    values.stream().filter(predicate).map(function).forEach(value -> {
>>      ...
>>    });
>>
>>    Optional<Value> optionalValue = somethingThatGivesAnOptional();
>>    if (optionalValue.isPresent()) {
>>      Value value = optionalValue.get();
>>      ...
>>    }
>>
>>    somethingThatGivesAnOptional().ifPresent(value -> {
>>      ...
>>    });
>>
>> In one case (really several cases that relied on the same utility)
>> that was enough to drive me to option (b).
>>
>> Option (b) allowed me to use the new lambda goodness but made me
>> slightly uncomfortable.  The utility in question could write values in
>> CSV format to an Appendable.  Since Appendable can throw IOExceptions,
>> I initially had the utility methods throw IOException.  To make it
>> lambda-friendly I changed all its methods to look like this:
>>
>>    try {
>>      ...
>>    } catch (IOException e) {
>>      throw new UncheckedIOException(e);
>>    }
>>
>> This was fine because I wasn't catching any IOExceptions that occurred
>> in the first place (this code was running in response to a web
>> request, and if an exception occurred the framework would handle it
>> and show an error page).  But I felt that it made my CSV utility a
>> little more "dangerous" for general use.  This is all sort of
>> hand-wavey, but I don't like that the utility now potentially throws
>> runtime exceptions when there's not a programmer error and when there
>> might be a reasonable way to recover.  Plus it is additional code in
>> my utility class, and good thing it is my class and not someone
>> else's.
>>
>> What I really wanted to do was leave in the checked exceptions *and*
>> use the lambda forEach/ifPresent forms.
>>
>> -Michael
>>



More information about the lambda-dev mailing list