0

To catch exceptions (even on constructors) in my tests elegantly I found the following solution in a blog and used it in all my projects on eclipse:

Throwable t= ThrowableCaptor.captureThrowable(() -> (new LinkedList<Object>()));

The ThrowableCaptor is implemented by a functional interface and some small extra code:

public class ThrowableCaptor {

    @FunctionalInterface
    public interface Actor {
        void act() throws Throwable;
    }

    public static Throwable captureThrowable(final Actor actor) {
        Throwable result = null;
        try {
            actor.act();
        }
        catch (final Throwable throwable) {
            result = throwable;
        }
        return result;
    }
}

Now, as I said, in Eclipse the thing worked like a charm. However under Netbeans I always get the following error message:

incompatible types: bad return type in lambda expression
LinkedList<Object> cannot be converted to void

Well, I have no clue, what is wrong...

Update 1 After some research I stumbled upon this:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=398734

I am not sure if it is related, but to my understanding, it suggests a problem with eclipse. Thus my code should indeed be the problem.

I assume, that the problem is matching new LinkedList<Object> to void act() throws Throwable. I"ll try generics as a solution.

Update 2 No Generics in Functional Interfaces...

Holger
  • 285,553
  • 42
  • 434
  • 765
grackkle
  • 776
  • 1
  • 9
  • 26

2 Answers2

1

You have made unnecessary work; it is not necessary to create two interfaces and captureThrowable methods. All you need is an understanding between Java Expressions and Expression Statements. The latter is an expression that is also allowed where a Statement is expected. new expressions are of the Expression Statement category while expressions put into braces are not.

In other words, all you had to do with your original statement:

Throwable t= ThrowableCaptor.captureThrowable(() -> (new LinkedList<Object>()));

is to remove the braces around new expression:

Throwable t= ThrowableCaptor.captureThrowable(() -> new LinkedList<Object>());

Note that you can further remove the unnecessary type arguments here:

Throwable t= ThrowableCaptor.captureThrowable(() -> (new LinkedList<>()));

or use a method reference:

Throwable t= ThrowableCaptor.captureThrowable(LinkedList::new);

Side notes:

  • An earlier version of javac had the bug of accepting braced expression in wrong contexts as well, see this question
  • If you had initially tagged your question with you had received an answer much earlier
Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765
  • Thanks for that answer. With that, I learned 3 things: 1) expressions vs. expression statements, 2) make my code much more readable 3) the java-8 tag. I made your answer the new solution, as it obviously is better than what I found. – grackkle Jan 27 '15 at 22:22
0

One can match to Actor only, when a method with return type void is called. Changing the return type to Object will allow all methods except those returning void. Therefore, the ThrowableCaptor needs a small upgrade, handling both cases by using two distinct functional interfaces. Looks to me like code duplication, but I don't see a nice way around it:

public class ThrowableCaptor {

    @FunctionalInterface
    public interface Actor {
        Object act() throws Throwable;
    }

    @FunctionalInterface
    public interface VoidActor {
        void act() throws Throwable;
    }

    public static Throwable captureThrowable(final Actor actor) {
        Throwable result = null;
        try {
            actor.act();
        }
        catch (final Throwable throwable) {
            result = throwable;
        }
        return result;
    }

    public static Throwable captureThrowable(final VoidActor actor) {
        Throwable result = null;
        try {
            actor.act();
        }
        catch (final Throwable throwable) {
            result = throwable;
        }
        return result;
    }
}
grackkle
  • 776
  • 1
  • 9
  • 26