Search code examples
javalambda

What is this Java construct `(InputStream is) -> () -> {}`


I don't understand this Java construct that I'm seeing in the documentation here.

public static <T,U> HttpResponse.BodySubscriber mapping(HttpResponse.BodySubscriber upstream, Function<? super T,? extends U> mapper)

The part that I think I understand but cannot seem to replicate is the example:

public static <W> HttpResponse.BodySubscriber<Supplier<W>> asJSON(Class<W> targetType) {
    HttpResponse.BodySubscriber<InputStream> upstream = HttpResponse.BodySubscribers.ofInputStream();
    HttpResponse.BodySubscriber<Supplier<W>> downstream = HttpResponse.BodySubscribers.mapping(
            upstream,
            (InputStream is) -> () -> {
                try (InputStream stream = is) {
                    ObjectMapper objectMapper = new ObjectMapper();
                    return objectMapper.readValue(stream, targetType);
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            }
        );

    return downstream;
}

Specifically the (InputStream is) -> () -> { part. When I read it I think it should be a Supplier that provides a Function that does what it does. However, when I try to code such a thing myself it doesn't work.

public static void main(String[] args) throws IOException {
    String r = myMethod((String s)->()->{return s + "ddd";});
}

public static String myMethod(Function<String, String> func) {
    return func.apply("Hello");
}

Gives me the compile err Target type of a lambda conversion must be an interface. However, Function is an interface.

What do I not understand?


Solution

  • HttpResponse.BodySubscribers.mapping takes as a 2nd parameter a value of type Function<? super T,​? extends U>. In your code T is InputStream and U is Supplier<W>, so the full type of mapping would be (ignoring the super\extends for brevity):

    Function<InputStream, Supplier<W>>
    

    Since a Supplier<W> has a single method of type W get(), a lambda expression for the Supplier type would be:

    () -> {/* return a value of type W*/}
    

    and therefore a lambda expression for mapper would be:

    (InputStream is) -> () -> {/* return a value of type W*/}
    

    which matches your code.