Does a method reference in Java 8 have a concrete type and if so, what is it? [duplicate]

一个人想着一个人 提交于 2019-11-29 08:01:43

First of all, method references "are compact, easy-to-read lambda expressions for methods that already have a name" (see The Java Tutorials - Method References).

So in fact, you are asking for the type of a lambda expression. This is clearly explained in JLS §15.27.3 (Type of a Lambda Expression).

In short, there are three compatibilities mentioned:

  1. Assignment context
  2. Invocation context
  3. Casting context

The type of a lambda expression or a method reference is inferred by the compiler. As now several contexts can (and must) be taken into account, Java 8 came with big enhancements for type inference.

The only restriction for lambda expressions is that the inferred type must be a functional interface. In fact, equal lambda expressions can have different types regarding to their context.

From the JLS, section 15.13.2, "Type of a Method Reference":

A method reference expression is compatible in an assignment context, invocation context, or casting context with a target type T if T is a functional interface type (§9.8) and the expression is congruent with the function type of the ground target type derived from T.

...

If a method reference expression is compatible with a target type T, then the type of the expression, U, is the ground target type derived from T.

Basically, the type of the method reference is whatever the context expects it to be. Independent of a context, the method reference doesn't really have a type. There's no way to pass around a "raw" method reference and then turn it into a Function or Consumer or whatever at some later point.

Method references are just a syntactic sugar for a function that uses passed parameter as an input argument. So, you can assign them this way:

Runnable runnable = System.out::println;
Consumer consumer = System.out::println;

types are inferred and depend on a context.

Your case:

Function<String, String> foo = helloGreeter::makeGreetingFor;

and it is equal to:

Function<String, String> foo = s -> helloGreeter.makeGreetingFor(s);

If you just have a method reference helloGreeter::makeGreetingFor, it has no type.

If you want to give a type to a method reference without assigning it or passing it as an argument (which assigns it to the parameter), you can cast it:

String greeting =
    ((Function<String, String>)helloGreeter::makeGreetingFor)
        .apply("Joe");
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!