– An alternative to Lambda expression is Method reference and constructor reference
– Both Method reference and Constructor reference allow us to reuse the existing code
– Double colon operator is used to make reference
– They provide code reusability
– They are used to map a method or constructor with corresponding single abstract method of a given functional interface
– Number of method arguments must be same as functional interface method
– But different return types are allowed
Method reference is another way of implementing functional programming in Java. Instead of creating anonymous method or Lambda expression, one can refer to existing method using that specific method name .
In simple words, it is a way of referencing an existing instance or static method with corresponding abstract method of functional interface. So that, it can be viewed as an instance of functional interface.
Syntax :
For instance method :
ObjetName :: MethodName
Let’s see a simple Java program to understand the working of Method Reference in case of instance method.
@FunctionalInterface // Not Compulsory interface ExampleInterface{ void print(); } public class MethodReferenceExample { void show(){ System.out.println("Body of show() would be used as print body"); } public static void main(String[] args) { MethodReferenceExample obj = new MethodReferenceExample(); ExampleInterface methodReference = obj ::show; methodReference.print(); } }
Output:
Body of show() would be used as print body
Explanation:
For referencing instance method, double colon operator is used, followed by object and lead by method name.
For Static Method
- ClassName: MethodName
Let’s see another simple Java code to understand the working of Method Reference in case of static Method.
@FunctionalInterface // Not Compulsory interface ExampleInterface{ void print(); } public class MethodReferenceExample { static void show(){ System.out.println("Body of show() would be used as print body: static method"); } public static void main(String[] args) { ExampleInterface methodReference = MethodReferenceExample::show; methodReference.print(); } }
Output:
Body of show() would be used as print body: static method
Explanation:
For referencing static method, double colon operator is used, followed by class name and lead by method name.
Constructor reference does the same thing but in different way, instead of referencing method, it maps the functional interface method with constructor of a particular class. It uses ‘new’ keyword to target a desirable constructor.
Let’s see another simple Java code to understand the working of Constructor Reference
@FunctionalInterface // Not Compulsory interface ExampleInterface{ void print(); } public class MethodReferenceExample { MethodReferenceExample() { System.out.println("This is a simple example constructor reference"); } public static void main(String[] args) { ExampleInterface methodReference = MethodReferenceExample ::new; methodReference.print(); } }
Output:
This is a simple example constructor reference
Explanation:
For referencing constructor, double colon operator is used, followed by class name and lead by new keyword.
]]>In Collection hierarchy, the iterable interface is the root interface in which a new feature has added namely forEach(). It allows iterating a collection of elements until the last element is processed.
It accepts consumer (functional interface) as an argument, meaning one needs to define a lambda expression that would take a single input and return nothing.
default void forEach(Consumer<? super T> action)
Functionality wise, forEach and enhanced for-loop are similar, but the new forEach is a type of internal loop. Meaning, the iterator handles iteration behind the scene, as a result, programmers don’t have to worry about the iteration behaviour.
Code Example:
Iterating over List:
import java.util.List; public class ForEachExample { public static void main(String[] args) { List nameList = new ArrayList(); nameList.add("Programmer"); nameList.add("ProgrammerBay"); nameList.add("coders"); nameList.forEach(singleItem -> System.out.println(singleItem)); } }
Output
Programmer ProgrammerBay coders
Iterating over Map:
import java.util.*; public class ForEachExample { public static void main(String[] args) { Map nameList = new LinkedHashMap(); nameList.put(1,"Programmer"); nameList.put(2,"ProgrammerBay"); nameList.put(4,"coders"); nameList.forEach((key,value) -> System.out.println("This is my key : "+key +" and value : "+value)); } }
Output:
This is my key : 1 and value : Programmer This is my key : 2 and value : ProgrammerBay This is my key : 4 and value : coders
Iterating over Stream of elements :
public class CreateStreams { public static void main(String[] args) { String[] stringArr = new String[]{"This", "is", "Example", "of", "Stream"}; // Creating Stream of Array Stream<String> arrayStream = Stream.of(stringArr); arrayStream.forEach(singleString -> System.out.print(singleString + " ")); } }
Output:
This is Example of Stream
Point to remember about forEach:
Points to remember:
– It is a final class that can handle null pointer exception while working with object.
– It comes under java.util.optional package.
– It is an efficient way of handling null checks that prevents NullPointerException.
– It produces concise code as it also helps us to avoid writing boilerplate codes(Bunch of if and else statements).
Some Important Methods
– isPresent() method identifies whether a value is there or not. It return false if it points to null value
– get() method is used to get values exist in Optional otherwise NoSuchElementException would be thrown
– orElse() : returns value if values are exist otherwise returns other
– empty() : Returns an empty Optional instance
– filter() : uses predicate to filter out undesired values
– map() : uses function to process logic over the given data
public class OpationalExample { public static void main(String[] args) { Integer[] arr = new Integer[1]; int num = arr[0]/10; System.out.println(num); } }
Error:
Exception in thread "main" java.lang.NullPointerException at OpationalExample.main(OpationalExample.java:9)
Explanation:
When we try to access an index position which simply doesn’t contain anything and try to perform operation on it, a runtime exception named NullPointerException is triggered. We can use Optional Class to deal with this problem.
import java.util.Optional; public class OpationalExample { public static void main(String[] args) { Integer[] arr = new Integer[1]; Optional<Integer > num = Optional.ofNullable(arr[0]); if(num.isPresent()) System.out.println("value :" +(num.get() /10)); else System.out.println("No value exist"); } }
Output:
No value exist]]>
-A default method allows to add a new methods in existing interface without affecting the implementing classes.
-It uses default modifier
– It must have a complete method definition. Basically, a dummy body.
– It is not compulsory for implementing class to override a default method but one can.
Prior to Java 8, a class that implements an interface mandatorily had to provide implementation to abstract methods of that particular interface.
However, it was not a big deal, but Java developers noticed that if there is an existing interface which has implemented by quite a large number of classes and there a need arises of adding another method. Then it would need to be overridden by other classes. This would break the code if any of the class omit to implement it.
Therefore, default method came in to picture, now one can add any new feature to existing interface without affecting behaviour of other implementing classes.
Before adding new Feature:
After adding new Feature:
For example:
interface MyInterface { default void display() { System.out.println("This is dummy definition"); } } public class DefaualtMethodExample implements MyInterface { public static void main(String[] args) { DefaualtMethodExample obj = new DefaualtMethodExample(); obj.display(); } }
Output:
This is dummy definition
– Java 8 also supports static method within an interface.
-Method body should be provided to the static method at the time of its declaration.
-It can’t be overridden in implementing classes
-It uses static modifier
– By default, static methods cannot be available in implementing classes. Therefore one need to call it by InterfaceName.methodName()
For example:
interface MyInterface { static void display() { System.out.println("This is static definition"); } } public class DefaualtMethodExample implements MyInterface { public static void main(String[] args) { MyInterface.display(); } }
Output:
This is static definition
]]>