1

I am learning method references in Java 8. I learnt that we can define functional interface method with either lambda or method reference. Method reference is a way of telling "there exist a similar method with same signature of functional interface method, you can call it". Further if that similar looking method exists as a static method, we call it using its class name. Or if it exists as non static way, then we will call it with object.

I am confused with below code.. EatSomething class has non-static similarToEat method, then why it is being called like a static method?

import java.util.function.*;

public class Test {
    public static void main(String[] args) {
        Test test = new Test();
        EatSomething es = new EatSomething();
        
        Function <EatSomething,String> ff1 = EatSomething::similarToEat; //here.. similarToEat is a non-static method, then why do I need to call it using class name?
        Function <EatSomething,String> ff2 = (EatSomething eat)->eat.similarToEat();
        Function <EatSomething,String> ff3 = es::eatOverloaded;
        
        
        System.out.println(test.process(ff1));
        
    }

    private String process(Function<EatSomething,String> func) {
        EatSomething es = new EatSomething();
        return func.apply(es);
    }
}


class EatSomething{
    public String similarToEat() {
        return "eat lightning, and crap thunder ";
    }
    
    public String eatOverloaded(EatSomething es) {
        return es.similarToEat();
    }

}

I am totally confused with this. Why should't I call similarToEat using object. Why do I have to use class name here? I can easily relate ff2 and ff3 objects in above code. Really confused with ff1.

One more piece of code..

interface MyCustomFunction{  
    String test(String abc);  
}  
public class MethodReference {  
     
    public static void main(String[] args) {  
        MethodReference mr = new MethodReference();
        MyCustomFunction func = String::toUpperCase; //here again. Why are we calling toUpperCase with its class name when its a non-static method
        System.out.println(mr.processs(func));
    }  
    public String processs(MyCustomFunction obj) {
        
        return obj.test("abc");
    }
}  
J. Doe
  • 69
  • 7
  • It's not getting called. The method declaration is being referenced on the `EatSomething` class. It only runs when explicitly invoked on an instance of `EatSomething` inside the `process` method. Also this is _horrible_ code, never write something like this =D – Mike 'Pomax' Kamermans Jul 12 '23 at 23:18
  • `MyCustomFunction func = String::toUpperCase;` here `MyCustomFunction` has a method lets say `String test(String abc); ` but `toUpperCase` is a non static method. Then why are we calling `toUpperCase` with its class name i.e. String. – J. Doe Jul 12 '23 at 23:40
  • 1
    Remember that terminology matters: we're not _calling_ anything. Calling a method/function means executing ("running") that method/function. We're _referencing_ a method here, using the method reference operator, `::`. The docs for which have already been linked to in the answer you accepted. – Mike 'Pomax' Kamermans Jul 13 '23 at 00:43
  • Yes. Actually this whole confusion arise due to this code : `public String extractUsername(String token) { // TODO Auto-generated method stub Function func = (Claims c)->c.getSubject(); // or Claims::getSubject return extractClaim(token,func); }` here a implemented method of Claims interface getSubject is called as if it is a static method. – J. Doe Jul 13 '23 at 05:21
  • So I treid to mimick that in my exercise session here. Understood now. If something is like `(Object o)->o.someMethod()` can be further shortened to `Object::someMethod` will remember that. – J. Doe Jul 13 '23 at 05:25

1 Answers1

3

You can call similarToEat using object, you will just get not a Function <EatSomething,String> but functional interface with zero-arg method like Callable/Runnable/Supplier since an instance of EatSomething is already defined by that object.

Here is Oracle documentation with types of method references:

Kind Syntax
Reference to a static method ContainingClass::staticMethodName.
Reference to an instance method of a particular object containingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type ContainingType::methodName

Look at examples:

    // denotes a method of any EatSomething instance that is not defined yet
    Function<EatSomething, String> ff1 = EatSomething::similarToEat; // thus we get a function from EatSomething to String
    // denotes a method of already specified EatSomething object
    Supplier<String> ff2 = es::similarToEat; // here we get a function without any argument
    Callable<String> ff3 = es::similarToEat; // it could be another FunctionalInterface with no-arg method
    
    ff1.apply(new EatSomething()); // we could provide any EatSomething object
    ff2.get(); // will execute similarToEat exactly against the es object
    ff3.call(); // will execute similarToEat exactly against the es object

What if EatSomething have a static method?

class EatSomething {
    public static String eatSomethingStaticMethod() {
        return "";
    }
}

Then taking method reference with a class name would return no-arg functional interface:

    Supplier<String> ff4 = EatSomething::eatSomethingStaticMethod;
    Callable<String> ff5 = EatSomething::eatSomethingStaticMethod;
gdomo
  • 1,650
  • 1
  • 9
  • 18
  • One more scenario, `MyCustomFunction func = String::toUpperCase;` here `MyCustomFunction` functional interface has a method lets say `String test(String abc); ` but `toUpperCase` is a non static method. Then why are we calling `toUpperCase` with its class name i.e. String. – J. Doe Jul 12 '23 at 23:42
  • 1
    Again, we can call it both ways and it would denote different things: `String::toUpperCase;` would return `Function` or `MyCustomFunction` and `"a"::toUpperCase` would return `Supplier` or another no-arg functional interface like `String test()` since target (string "a") is previously defined – gdomo Jul 12 '23 at 23:49