3
\$\begingroup\$

I am currently trying to learn Lambdas and following the book Java SE8 for the really Impatient and just finished Chapter 1 of it. This is the question, I am trying to get done with:

Didn’t you always hate it that you had to deal with checked exceptions in a Runnable? Write a method uncheck that catches all checked exceptions and turns them into unchecked exceptions. For example,

new Thread(uncheck( () -> { System.out.println("Zzz"); Thread.sleep(1000); })).start(); // Look, no catch (InterruptedException)!

Hint: Define an interface RunnableEx whose run method may throw any exceptions. Then implement public static Runnable uncheck(RunnableEx runner). Use a lambda expression inside the uncheck function. Why can’t you just use Callable<Void> instead of RunnableEx?

This is my solution:

@FunctionalInterface
public interface RunnableEx extends Runnable {
    @Override
    default void run () {
        try {
            doRun();
        } catch (Error | RuntimeException e) {
            throw e;
        } catch (Throwable throwable) {
            throw new IndexOutOfBoundsException("IOBE");
        }
    }

    void doRun ()
        throws Throwable;
}

and

public class Question6 {
    public static void main (String... args) {
        uncheck(() -> {
            System.out.println("Question6");
        });
    }

    public static Runnable uncheck (final RunnableEx runner) {
        final RunnableEx runnable = () -> {
            try {
                runner.doRun();
            } catch (Error | RuntimeException e) {
                throw e;
            } catch (Throwable ignored) {
                runner.doRun();
            }
        };

        return runnable;
    }

    // We can not use Callable<Void> because it throws Checked Exception.
}

I request two things:

  1. How can this be improved, if it can be?
  2. As per my understanding, this implementation seems to be correct, but is it really?
\$\endgroup\$
6
\$\begingroup\$
default void run () {

There should be no blank after a method name (neither in a declaration not in a call). There are only blanks after if and while to distinguish them visually from method calls.


    try {
        doRun();
    } catch (Error | RuntimeException e) {
        throw e;
    } catch (Throwable throwable) {
        throw new IndexOutOfBoundsException("IOBE");
    }

Really IndexOutOfBoundsException??? What index, what bounds? It should be

    try {
        doRun();
    } catch (Error | RuntimeException e) {
        throw e;
    } catch (Throwable e) {
        throw new RuntimeException(e);
    }

It's called exception wrapping. You can't throw e, so you wrap it into a RuntimeException and it can be obtained via getCause. Printing the stack does it, so you lose no information.


    final RunnableEx runnable = () -> {
        try {
            runner.doRun();
        } catch (Error | RuntimeException e) {
            throw e;
        } catch (Throwable ignored) {
            runner.doRun();
        }
    };

The line runner.doRun() makes no sense to me. It failed, so you do it again. Why?

Moreover, it may throw a Throwable.

Moreover, you're repeating what you did above.

You've been already given a workable example in the question:

new Thread(uncheck( () -> { System.out.println("Zzz"); Thread.sleep(1000); })).start(); // Look, no catch (InterruptedException)!
\$\endgroup\$
  • \$\begingroup\$ Thanks for suggestions. As far as IndexOutOfBoundException is concerned, I just wanted to throw any Unchecked exception but yes your point is very valid. \$\endgroup\$ – D D Jul 16 '15 at 0:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.