Say, for the following example:
public class MyConsumer {
public void accept(int i) {}
public static void biAccept(MyConsumer mc, int i) {}
}
public class BiConsumerDemo {
public void accept(int i) { }
public static void biAccept(MyConsumer mc, int i) { }
private void testBiConsume() {
BiConsumer<MyConsumer, Integer> accumulator = (x, y) -> {}; // no problem, method accepts 2 parameters
accumulator = MyConsumer::accept; // accepts only one parameter and yet is treated as BiConsumer
accumulator = MyConsumer::biAccept; // needed to be static
accumulator = BiConsumerDemo::accept; // compilation error, only accepts single parameter
}
}
Why is that the variable accumulator
, which is a BiConsumer
that requires a function to accept 2 parameters, can be assigned with MyConsumer::accept
when that method only accepts only a single parameter?
What is the principle behind this language design in Java? If there's a term for it, what is it?
Interface BiConsumer<T,U> Represents an operation that accepts two input arguments and returns no result. This is the two-arity specialization of Consumer . Unlike most other functional interfaces, BiConsumer is expected to operate via side-effects.
March 8, 2020. Java BiConsumer is a built-in Functional interface in java, represents an operation that accepts two input arguments and returns no result. This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.
Explanation. BiFunction<T,U> functional interface represents an operation that accepts two input arguments, and returns a result.
MyConsumer::accept
is a method reference to an instance method of MyConsumer
class that has a single argument of type int
. The MyConsumer
instance on which the method is called is considered an implicit argument of the method reference.
Therefore:
accumulator = MyConsumer::accept;
is equivalent to:
accumulator = (MyConsumer m,Integer i) -> m.accept(i);
given a targeted function type with n parameters, a set of potentially applicable methods is identified:
If the method reference expression has the form ReferenceType :: [TypeArguments] Identifier, the potentially applicable methods are the member methods of the type to search that have an appropriate name (given by Identifier), accessibility, arity (n or n-1), and type argument arity (derived from [TypeArguments]), as specified in §15.12.2.1.
Two different arities, n and n-1, are considered, to account for the possibility that this form refers to either a static method or an instance method.
(from 15.13.1. Compile-Time Declaration of a Method Reference )
In your case the target function type is BiConsumer
, which has 2 parameters. Therefore any methods of the MyConsumer
class matching the name accept
and having 2 or 1 parameters are considered.
Both static methods having 2 parameters and instance methods having 1 parameter can match the target function type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With