Hello guys, I am back with a new blog. This blog is an extension of two previous blogs listed below. I would recommend you to go through these blogs before starting with this one.
Interface Evolution (Java 7, Java 8, Java 9)
In this blog, we will see how interface evolve across java versions
Internal working of the functional interface and lambda expression
This blog will help you to understand how JVM handles functional interface and lambda expression.
In this blog, we will look into some simple but important points with respect to Type Inferences, Lambda Expressions, and Method References. Lets us start with type inferences.
Type inference was introduced in Java 5 in the form of Generics. Type inference is the Java compiler’s ability to look at each method invocation and corresponding declaration to determine the type argument
Let us understand with the help of an example.
In the above example, the code doesn’t specify the type argument for the “print” method. Here, the type parameter is inferred from the method invocation ie the first print method invocation takes an int. So, the argument of the print method becomes an int. Similarly, for the next print method invocation, the argument becomes a string type.
Let us now look at how type inferences work in case of a lambda expression with the help of an example.
If you see the above example, the parameter “value” in the lambda expression is of type String. It is inferred from the type provided by the Consumer.
Type can be inferred in 4 possible ways
- RHS of assignment (Consumer<String = lambda)
- Actual parameter of a method or a constructor (new Thread(lambda) — Thread takes Runnable as an input)
- The argument of ‘return’ (return lambda)
- The argument of a cast ((Consumer<String>) lambda)
Let us move on to lambda expressions. Before we start, let us go back in time where we used to write anonymous classes like the one I have written below
Look at the above example and try to figure out how many objects are going to be created? Try it on your own!!!!
Yes, I know the answer, 5 objects will be created. Now, let us try out with lambda expression.
Now guess the answer. Do you still think that 5 objects are going to be created? If you still think 5 then your answer is wrong.
Let us try out with Capturing Lambdas with static and non-static fields
As you can see lambda expression provides a lot of benefits over the traditional approach. Now, let us talk about method reference.
Normally, you use lambda expressions to create anonymous methods. Sometimes, a lambda expression does nothing but call an existing method. In those cases, it’s often clearer to refer to the existing method by name. Method reference enables you to do this. They are compact, easy to read lambda expressions for methods that already have a name. Let us understand with the help of an example.
If you see the signature of the println method. It matches the signature of the consumer interface. And in the lambda expression, we are just calling the println method. This lambda expression can be replaced by the method reference where System.out is the object and println is the method of that object.
Forms of Method References
- Static method (Employee::getMaxSalary)
- Instance method, unspecified instance (Employee::getSalary)
- Instance method, specified instance (mike::getSalary)
- Constructor (Employee::new)
- Instance method of the superclass (super::food)
- Array constructor (A::new)
A method reference or a lambda expression can be applied to more than one interface with the same signature. See the example below.
Let us apply our knowledge in one of the use cases where I have created an Employee class. Now my task is to display the details based on the requirement. Here is an example.
If you see the above example, I have created a common method to display any kind of information. This is possible with the help of lambda expression and functional interface. Try experimenting with the features provided in Java 8.
That’s all from this blog. Keep reading and do send me your feedback and comments. Do subscribe!!!