I have the following piece of code, that uses java Functional Interfaces, that compiles, but it's not clear why does it compile:
public class App {
public static void main(String[] args) throws Exception {
final RecordIterator it = new RecordIterator<MyRecord>();
final UpdateManager updateManager = new UpdateManager();
updateManager.doUpdateForEach(it, DatabaseOperator::updateInfo);
}
}
class UpdateManager {
public void doUpdateForEach(final RecordIterator recordIterator,
final FunctionalStuff<MyRecord> updateAction) throws Exception {
updateAction.execute(new DatabaseOperator(), new MyRecord());
}
}
class RecordIterator<E> {
}
@FunctionalInterface
interface FunctionalStuff<T> {
void execute(final DatabaseOperator database, final T iterator) throws Exception;
}
class DatabaseOperator {
public void updateInfo(final MyRecord r) {
}
}
class MyRecord {
}
So, my confusion is inside of the main
method:
updateManager.doUpdateForEach(it, DatabaseOperator::updateInfo);
UpdateManager#doUpdateForEach
method expects a RecordIterator
(ok, makes sense), and a FunctionalStuff
FunctionalStuff
has a single method (obviously), that receives 2 paramsdoUpdateForEach
is a method reference (DatabaseOperator::updateInfo
)DatabaseOperator::updateInfo
method receives a single argumenthow does this compiles? How is the DatabaseOperator::updateInfo
method reference converted into the functional interface? Am I missing something obvious? Or is some corner case of functional interfaces?
Surely lambda expression can be one-time used as your commented code does, but when it comes to passing lambda expression as parameter to mimic function callback, functional interface is a must because in that case the variable data type is the functional interface.
Replace functional interface with Function.
They can be implemented and instantiated using anonymous class syntax. For example, take the ITrade functional interface.
A functional interface in Java is an interface that contains only a single abstract (unimplemented) method. A functional interface can contain default and static methods which do have an implementation, in addition to the single unimplemented method.
How is the
DatabaseOperator::updateInfo
method reference converted into the functional interface?
The effective lambda representation of your method reference is :
updateManager.doUpdateForEach(it, (databaseOperator, r) -> databaseOperator.updateInfo(r));
which is further representation of anonymous class:
new FunctionalStuff<MyRecord>() {
@Override
public void execute(DatabaseOperator databaseOperator, MyRecord r) throws Exception {
databaseOperator.updateInfo(r);
}
});
First of all, FunctionalStuff<T>
is defined like that:
@FunctionalInterface
interface FunctionalStuff<T> {
void execute(final DatabaseOperator database, final T iterator) throws Exception;
}
The method reference DatabaseOperator::updateInfo
is converted to an instance of FunctionalStuff<MyRecord>
like that (I left the actual types for clearification, but they can be omitted):
FunctionalStuff<MyRecord> func = (DatabaseOperator database, MyRecord r) -> database.updateInfo(r);
Or if you want to use it as an anonymous class:
FunctionalStuff<MyRecord> func = new FunctionalStuff<MyRecord>() {
void execute(final DatabaseOperator database, final MyRecord r) {
database.updateInfo(r);
}
}
See the tutorial with the following example:
Reference to an instance method of an arbitrary object of a particular type
The following is an example of a reference to an instance method of an arbitrary object of a particular type:
String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" }; Arrays.sort(stringArray, String::compareToIgnoreCase);
The equivalent lambda expression for the method reference
String::compareToIgnoreCase
would have the formal parameter list(String a, String b)
, wherea
andb
are arbitrary names used to better describe this example. The method reference would invoke the methoda.compareToIgnoreCase(b)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With