Calling a method from the result of a lambda function
I have an object ( Adult
) with another object ( Child
) as a parameter. I am trying to write Function
which will return a child name if provided by an adult.
I wrote this:
public static void main(String[] args) {
Function<Adult, Object> adult_name_f = Adult::getName;
Function<Adult, Object> adult_child_f = Adult::getChild;
Function<Adult, Object> child_name_f = Adult::getChild.getName;
}
static class Adult {
String name;
Child child;
public Child getChild() {
return child;
}
public String getName() {
return name;
}
}
static class Child {
String name;
public String getName() {
return name;
}
}
but (obviously) Adult::getChild.getName
invalid Function
.
Is there a way to return the child's name if specified by an adult?
source to share
First, you must specify the appropriate return type Function
.
Function<Adult, String> adult_name_f = Adult::getName;
Function<Adult, Child> adult_child_f = Adult::getChild;
Then you can use the method Function.andThen()
to create the third one Function
.
Function<Adult, String> child_name_f = adult_child_f.andThen(Child::getName);
Alternatively, and most often for chaining methods, you can define Function
using a lambda expression. You can even use lambda expressions for the first two, but method reference is better (less generated code).
Function<Adult, String> adult_name_f = a -> a.getName();
Function<Adult, Child> adult_child_f = a -> a.getChild();
Function<Adult, String> child_name_f = a -> a.getChild().getName();
Test
Adult mary = new Adult("Mary", new Child("Jesus"));
System.out.println(adult_name_f.apply(mary)); // prints: Mary
System.out.println(adult_child_f.apply(mary)); // prints: Test$Child@XXXXXXXX
System.out.println(child_name_f.apply(mary)); // prints: Jesus
source to share
The easiest way is to just use lambda.
Function<Adult, Object> child_name_f = adult -> adult.getChild().getName();
Note that this is the syntax for what Java calls "lambda". The syntax you used in your question is a method reference, not a lambda, but the two are closely related. A method reference can always be expressed as a lambda. Thus:
Function<Adult, Object> adult_name_f = Adult::getName;
equivalent to
Function<Adult, Object> adult_name_f = adult -> adult.getName();
[There may be differences in how they are implemented, but the effect is the same for all practical purposes.]
If you want to call two methods, there is no easy way to do it using the method reference syntax, but the lambda works just fine.
See How do I compose functions? for some other ideas on how you can create a function composition from two method references. I think these answers are interesting, but in real life I still use lambda.
source to share