Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected Java Functional Interface conversion

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:

  • the last line of the main method is updateManager.doUpdateForEach(it, DatabaseOperator::updateInfo);
  • the UpdateManager#doUpdateForEach method expects a RecordIterator (ok, makes sense), and a FunctionalStuff
  • FunctionalStuff has a single method (obviously), that receives 2 params
  • The second argument of the doUpdateForEach is a method reference (DatabaseOperator::updateInfo)
  • The DatabaseOperator::updateInfo method receives a single argument

how 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?

like image 838
pedrorijo91 Avatar asked Dec 27 '18 12:12

pedrorijo91


People also ask

Can we write lambda without functional interface?

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.

Which is the replacement for functional interface?

Replace functional interface with Function.

Can functional interface be instantiated?

They can be implemented and instantiated using anonymous class syntax. For example, take the ITrade functional interface.

What is a functional interface Java?

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.


2 Answers

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);
    }
});
like image 183
Naman Avatar answered Oct 23 '22 06:10

Naman


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), where a and b are arbitrary names used to better describe this example. The method reference would invoke the method a.compareToIgnoreCase(b).

like image 21
Dorian Gray Avatar answered Oct 23 '22 06:10

Dorian Gray