Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is BiConsumer allowed to be assigned with a function that only accepts a single parameter?

Tags:

lambda

java-8

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?

like image 737
supertonsky Avatar asked Feb 18 '18 13:02

supertonsky


People also ask

What is BiConsumer in functional interface?

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.

What is BiConsumer Java?

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.

Is method reference only applicable for functional interface?

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.

Which functional interface represents an operation that accepts two input arguments and returns a result?

Explanation. BiFunction<T,U> functional interface represents an operation that accepts two input arguments, and returns a result.


1 Answers

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.

like image 161
Eran Avatar answered Jan 09 '23 13:01

Eran