As part of the JSR-335 (Project Lambda) which adds closure support to Java language, there were quite a few changes in the language to support the use of closures in the existing Java APIs (Collection APIs to a large extent). One such change is the introduction of Virtual Extension Methods.
also read:
We all are aware of the fact that the interfaces don’t contain any implementation for the methods. To provide support for new APIs which support the use of closures and also which can run on Multi core platforms there has to be some way to add these APIs to existing classes. For example, methods like forEach, map, reduce, filter which act on a collection can be added to the Collection class directly or create a new interface and let all the collection API implement them or leave it to the user of the API to implement the new interface. The first 2 approaches would lead to breaking lots of existing code because of the lack of implementation of these new methods in the interface. The last approach is possible, but it doesn’t enhance the collection API out of the box.
The team which handles JSR-335 thought of a way to add default implementation to the interfaces, which gives an option for the implementor to override the method or to leave it as is. This way new APIs can be added to the Collection class without breaking the existing code and yet provide the full support of the closures to the existing code. One can read in depth about Virtual Extension Methods here.
Lets see an example of a virtual extension method:
interface TestInterface{ public void testMe(); public void aDefaulter() default{ System.out.println("Default from interface"); } }
Using the “default” keyword we can add new methods to the existing interface and allowing the implementing classes to use this default implementation if they don’t override. Something like:
public class DefenderMethods{ public static void main(String[] args){ InterfaceImplementer imp = new InterfaceImplementer(); imp.testMe(); imp.aDefaulter(); } } class InterfaceImplementer implements TestInterface{ public void testMe(){ System.out.println("Hello World!"); } }
The output for above program would be:
~/javaP/java8$ javac DefenderMethods.java ~/javaP/java8$ java DefenderMethods Hello World! Default from interface
Moving further, we can override the aDefaulter method in its implementing class, something like
class InterfaceImplementer implements TestInterface{ public void testMe(){ System.out.println("Hello World!"); } public void aDefaulter(){ System.out.println("Defautler overridden from class"); } }
for which the output will be:
~/javaP/java8$ javac DefenderMethods.java ~/javaP/java8$ java DefenderMethods Hello World! Defautler overridden from class
The bytecode generated for the DefenderMethods class still uses invokevirtual opcode for invoking the default method, which indicates its treated like any other usual interface method in its invocation.
There’s lot more to this concept like overriding rules, method invocation rules which I would like to cover in subsequent posts. And also sample code from the JDK 8 which uses this feature.