Issue in understanding the working of Method Referencing

Viewed 51

I am trying to understand the working of Method Reference: Note: I did go through the link :: (double colon) operator in Java 8 and fw other related articles.

I am trying to call addMoney() method using method referencing. Add money is an instance method and it does not take any argument but returns a Money object. For this scenario we can use Supplier which has

<R> get() 

It takes in no arguments and returns type.

    Money money = new Money(2);
    Supplier<Money> supplier = money::addMoney;

And this works as expected.

But when I give in the similar way it also works, not sure why and how:

    Function<Money, Money> addingMoney = Money::addMoney;
    Consumer<Money> returnMoney = Money::addMoney;

This does not make sense at all for me as addMoney method is instance method and we are accessing it using Class Name and moreover for method referencing to work the arguments must match even that is not happening here. Could you someone please guide.

For the below class I am able to write a

class Money{
    private int moneyValue =0;

    public Money(int i) {
        // TODO Auto-generated constructor stub
    }
    
    public Money addMoney(){
        this.moneyValue+=10;
        System.out.println("We are adding money");
        return this; 
    }
    
    public Money spendMoney(){
        System.out.println("We are deducting money");
        this.moneyValue-=10;
        return this; 
    }

    public int getMoneyValue() {
        return this.moneyValue;
    }
    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return this.moneyValue+"";
    }
    
}
1 Answers

When the method reference is called from the class but it is an instance method : it needs an instance to work.

That's why Function<Money, Money> addingMoney = Money::addMoney; works

  • like the Supplier, it returns a Money instance (2nd generic type)
  • as it is an instance method, it needs a Money instance as input (1st generic type)

That's why Consumer<Money> returnMoney = Money::addMoney; works

  • it is like half of the Function, it takes the instance as input
  • but you tell that you don't care of the result

Then lambda equivalent may help you

// no input but care about output
Supplier<Money> supplier = money::addMoney;
Supplier<Money> supplier = () -> money.addMoney();

// care about output and needs input
Function<Money, Money> addingMoney = Money::addMoney;
Function<Money, Money> addingMoney = money1 -> money1.addMoney();

// don't care about output but needs input
Consumer<Money> returnMoney = Money::addMoney;
Consumer<Money> returnMoney = money1 -> money1.addMoney();
Related