2

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+"";
    }
    
}
User27854
  • 824
  • 1
  • 16
  • 40

1 Answers1

2

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();
azro
  • 53,056
  • 7
  • 34
  • 70
  • Would it be wrong to say that while performing method referencing, the number of arguments must match? We can observer that add Money method does not have any arguments where as the abstract method defined in the Function interface takes in an argument. – User27854 Jun 12 '21 at 10:55
  • @User27854 The function needs an argument because that is how Function works – azro Jun 12 '21 at 10:56
  • While reading a blog, they had mentioned that for Method referencing to work the number of arguments defined in the abstract method in our case R apply(T t) for function must match with the number of arguments defined in the addMoney method. Is this observation correct? – User27854 Jun 12 '21 at 11:00