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");
}
}
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;