Just to add to the answer from Eran, you can possibly find a real life example better to understand.
Let's assume we have a method that adds an Integer i and an intValue of a Long l to return back as a String s representation. This would look like :
String convertToStringAfterAddingValues(Long l, Integer i) {
return String.valueOf(l.intValue() + i);
}
In the world of FunctionalInterface, this could be represented as a BiFunction as an anonymous class:
BiFunction<Long, Integer, String> biFunctionAnonymous = new BiFunction<Long, Integer, String>() {
@Override
public String apply(Long l, Integer i) {
return String.valueOf(l.intValue() + i);
}
};
which in the lambda world could then be represented as:
BiFunction<Long, Integer, String> biFunctLambda = (l, i) -> String.valueOf(l.intValue() + i);
the same can be represented using method reference with the object of the class the method resides in as :
BiFunction<Long, Integer, String> biFunctMethodReference = <YourClassInstance>::convertToStringAfterAddingValues;