Informal explanation:
Remember that method references can be thought of as an alternate syntax for some lambdas, and that lambdas all implement one or more functional interfaces.
And remember that lambdas are (currently) a way to write some single-method anonymous classes in a much more concise form; thus, lambdas can always be reduced to a anonymous class (but not always the other way around).
So
foo (A::method1);
can become
foo ((c) -> <body>);
which can be reduced to the anonymous class:
foo (new Function<B>() {
<body>
});
which is an anonymous class that is a subtype of Function
Method references are thus anonymous subtypes of whatever functional interface they represent, and so the type of the parameter has to be the corresponding functional interface or one of its supertypes.
The JLS actually has a section titled "15.13.2. Type of a Method Reference", but the wording might be a bit obtuse. In short:
A method reference can be used as a type T
if:
T
is a functional interface type (section 9.8)
- The functional interface's abstract method matches the compile-time type of the method reference
- Either:
- The reference returns
void
- The reference returns a type that can be assigned to the corresponding type of the functional interface, e.g. A method reference has to return
Number
or a subtype to be compatible with `B foo(Function f)