How to tell Java to apply a lambda expressions for a custom functional interface instead for the one from the method’s contract?
The lambdas are without any doubt one of the most intriguing and attractive features in Java 8, but sometimes instead of helping us writing a better and boilerplateless code, they can get us into trouble. And still, they are the better alternative to the anonymous classes for lots of reasons. The anonymous classes were a […]
The lambdas are without any doubt one of the most intriguing and attractive features in Java 8, but sometimes instead of helping us writing a better and boilerplateless code, they can get us into trouble. And still, they are the better alternative to the anonymous classes for lots of reasons.
The anonymous classes were a nice way to achieve clojures in Java, but it was something natural to write a lot of boilerplate code to achieve something atomic. Let take a look on the following code snippet:
It does a single thing - writing a message on the standard output, but in order to have it implemented, we wrote five lines of code. Which is not really cool and is a sign for a boilerplate code.
The same statement, but written with the terms of lambdas, would look like:
This looks pretty neat and more readable, isn't it ? :-)
But, there is, however, a problem with the lambda approach! Let's first get back to the anonymous class and write our own implementation of the java.awt.event.ActionListener interface, which has a member variable within:
Using anonymous classes, it won't be a problem to create an anonymous implementation of MyActionListener and even to refer the nester member within the implementation:
Now the question that stands is how to achieve the same functionality using lambdas?
The following snippet doesn't compile:
because the lambda expression we're using is actually the implementation of the ActionListener#actionPerformed(ActionEvent e) method, not the MyActionListener#actionPerformed(ActionEvent e) method and this is why it fails to compile - the compiler doesn't know about the variable fourtyTwo since it's not defined in the ActionListener interface.
Now the problem is how to tell the JVM that the lambda we're using is actual implementation of the MyActionListener#actionPerformed(ActionEvent e)? And the answer is the following:
In Java 8 the abstract classes are not functional interfaces, even if they contain a single abstract method! This is why, we can't cast the lambda to MyActionListener when passing and to expect to have our hands on the variable named fourtyTwo. On the other hand, however, functional interfaces can be extended and so we can create functional interfaces of our own.
This is enough to say that our interface is functional, because
MyActionListener is an interface and not an abstract class
MyActionListener has a single abstract method and this is the derived ActionListener#actionPerformed(ActionEvent e)
Now we can write the lambda expression, which would be an implementation of MyActionListener#actionPerformed(ActionEvent e) and pass it to the myButton.addActionListener() method:
it compiles and successfully accesses the member variable and therefore the problem is solved.
Cheers!
Sign up for our newsletter and never miss an article
[mc4wp_form id=8036]
Manage Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.