3

I'm doing some tests using lambda expressions but my code does not compile. My lambda implementation is wrong or the exception handling? What would be the correct implementation of the following code?

class MyObject { }

interface Creatable<T> {
    T create() throws IOException;
}

/* Using the code: */
Creatable<MyObject> creator = () ->  {
    try {
        return new MyObject();
    } catch (IOException e) {
        e.printStackTrace();
    }
};

MyObject obj1 = creator.create();

If i remove the try catch block and declare the exception to throw in the method, the code compiles and runs normally.

Creatable<MyObject> creator = () -> new MyObject();

The compilation error is:

incompatible types: bad return type in lambda expression

1
  • 2
    This actually doesn't have much to do with the lambda. The same method body won't compile if you declare it the normal way. The error message just isn't particularly informative. Commented Jun 3, 2014 at 0:50

3 Answers 3

6

Your lambda needs to return a MyObject. If the try block completes successfully that is the case, but if it doesn't the catch block is executed which does not return anything. So you could write:

Creatable<MyObject> creator = () ->  {
    try {
        return new MyObject();
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
};

But then you will get another compile error: "IOException is never thrown in try block". So you would also need to have a constructor in MyObject that throws an IOException:

class MyObject { MyObject() throws IOException {} }

In the end, unless MyObject actually throws an exception, you can simply use:

Creatable<MyObject> creator = () -> new MyObject();

which you can also write:

Creatable<MyObject> creator = MyObject::new;
Sign up to request clarification or add additional context in comments.

1 Comment

Even if new MyObject() theos an exception, you can write it like that. In any case, the user of this interface must be prepared to get an IOException out of it. That's the point of implementing the interface in exactly this way.
1

Lambda needs all paths to return the value as mentioned in the previous answer the easy solution is to return at the end of the catch block

However there is a more elegant way to handle exception when using lambda

you can wrap a lambda with another Example wrap(((x,y)->x/y))

Biconsumer<Integer,Integer> consumer wrap(Biconsumer<Integer,Integer> consumer)    
{    
return (v,k)->{try

{consumer.apply()}

catch(){};

}

https://www.youtube.com/watch?v=YLKMCPMLv60&list=PLqq-6Pq4lTTa9YGfyhyW2CqdtW9RtY-I3&index=18

Comments

0
@FunctionalInterface
public interface CreateThrowable<T, R, E extends Throwable> {
   R create(T t) throws E;
static <T, R, E extends Throwable> Function<T, R> uncheckedException(ThrowingFunction<T, R, E> f) {
    return t -> {
        try {
            return f.create(t);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    };
}

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.