Functional Interfaces

Interface that contains only one abstract method. This doesn’t mean that it cannot contain other non-abstract methods.

Normally, these interfaces are declared with @FunctionalInterface (Optional) which will allow the compiler to understand that it’s a Functional Interface. Nothing special though with this annotation.

Functional Interface also known as Single Abstract Method Interfaces or SAM Interfaces. It is a new feature in Java, which helps to achieve functional programming approach.

Example : –

@FunctionalInterface 

interface sayable{ 

 void say(String msg); 

}
public class FunctionalInterfaceExample implements sayable{ 

 public void say(String msg){ 

 System.out.println(msg); 

 } 

 public static void main(String[] args) { 

 FunctionalInterfaceExample fie = new FunctionalInterfaceExample(); 

 fie.say("Hello there"); 

 } 

}

A functional Interface can have methods of Object class also.

@FunctionalInterface 

interface sayable{ 

 void say(String msg); // abstract method 

 // It can contain any number of methods of Object class. 

 int hashCode(); 

 String toString(); 

 boolean equals(Object obj); 

}

A functional interface can extend other interfaces only if the other Interface (Parent Interface) does not have any abstract method.

Example: – functional interface trying extending an interface having an abstract method and getting an error displayed in the comments.

interface sayable{ 

 void say(String msg); // abstract method 

}
@FunctionalInterface 

interface doable extends sayable{ 

 // Invalid '@FunctionalInterface' annotation; doable is not a functional interface 

 void doIt(); 

}

Example: – functional interface extending an interface having a non-abstract method

interface doable{ 

 default void doIt(){ 

 System.out.println("Do it now"); 

 } 

}
@FunctionalInterface 

interface sayable extends doable{ 

 void say(String msg); // abstract method 

}
public class FunctionalInterfaceExample implements sayable{ 

 public void say(String msg){ 

 System.out.println(msg); 

 } 

 public static void main(String[] args) { 

 FunctionalInterfaceExample fie = new FunctionalInterfaceExample(); 

 fie.say("Hello there"); 

 fie.doIt(); 

 } 

}

Method references

Java provides a new feature called method reference in Java 8. Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.

There are four types of method references:

  1. Reference to a static method.

  2. Reference to an instance method of a particular object.

  3. Reference to an instance method of an arbitrary object of a particular type.

  4. Reference to a constructor.

Reference to a static method

You can refer to static method defined in the class or outside the class. Following is the syntax and example which describe the process of referring static method in Java.

Syntax:

ContainingClass::staticMethodName

Example: – calling a static method saySomething() within the MethodReference class

interface Sayable{ 

 void say(); 

} 

public class MethodReference { 

 public static void saySomething(){ 

 System.out.println("Hello, this is static method."); 

 } 

 public static void main(String[] args) { 

 // Referring static method 

 Sayable sayable = MethodReference::saySomething; 

 // Calling interface method 

 sayable.say(); 

 } 

}

Example: – calling a static method of another class

interface Sayable{ 

 void say(); 

} 

Public class AnotherClass{

 public static void saySomething(){ 

 System.out.println("Hello, this is static method."); 

 }

}

public class MethodReference { 

 public static void main(String[] args) { 

 // Referring static method 

 Sayable sayable = AnotherClass::saySomething; 

 // Calling interface method 

 sayable.say(); 

 }

Reference to an instance (non static) method of a particular object

We can refer to the method of functional interface via a non static (instance method) by using the following syntax

ObjectOfContainingClass :: nonStaticMethodName()

Example: – Referring non-static methods. You can refer methods by class object and anonymous object.

interface Sayable{ 

 void say(); 

} 

publicclass MethodReference { 

 public void saySomething(){ 

 System.out.println("Hello, this is non-static method."); 

 } 

 public static void main(String[] args) { 

 MethodReference methodReference = new MethodReference(); // Creating object 

 // Referring non-static method using reference 

 Sayable sayable = methodReference::saySomething; 

 // Calling interface method 

 sayable.say(); 

 // Referring non-static method using anonymous object 

 Sayable sayable2 = new MethodReference()::saySomething; // You can use anonymous object also 

 // Calling interface method 

 sayable2.say(); 

 } 

}

Example: – Referring instance (non-static) method. Runnable interface contains only one abstract method. So, we can use it as functional interface.

public class InstanceMethodReference { 

 public void printnMsg(){ 

 System.out.println("Hello, this is instance method"); 

 } 

 public static void main(String[] args) { 

 Thread t2=new Thread(new InstanceMethodReference()::printnMsg); 

 t2.start(); 

 } 

}

Reference to an instance method of an arbitrary object of a particular type

Instance method of an arbitrary object of a particular type can be referred using the syntax

ContainingType::methodName

Example : –

import java.util.ArrayList;

import java.util.List;

public class TestArbitraryObjectMethodRef{

 public static void main(String args[]){

 List<Person> persons = new ArrayList<Person>(0);

 Person p1 = new Person();

 p1.setName("P1");

 p1.setAge(1);


 


 Person p2 = new Person();

 p2.setName("P2");

 p2.setAge(2);

 persons.add(p1);

 persons.add(p2);

 persons.forEach(Person::display); //14

}

}
class Person{

 private String name;

 private int age;

 public String getName() {

 return name;

 }

 public void setName(String name) {

 this.name = name;

 }

 public int getAge() {

 return age;

 }

 public void setAge(int age) {

 this.age = age;

 }

 public void display(){

 System.out.println("Name: "+name + " Age: "+age);

 }

}

Here it should be noted that display is an instance method which will be called for each object of type Person in the list. You might know the fact that instance methods can be called only on an object reference. Here the object reference is an arbitrary one.

The same statement (#14) can be written using lambda expression as follows,

persons.forEach(person->System.out.println(“Name: “+person.getName() + ” Age: “+person.getAge()));

Reference to a Constructor

You can refer a constructor by using the new keyword. Here, we are referring constructor with the help of functional interface.

Syntax

ClassName::new

Example: – here we can refer the method of a functional interface via a constructor by calling the class name (whose constructor is to be called)::new keyword.

interface Messageable{ 

 Message getMessage(String msg); 

} 

class Message{ 

 public Message(String msg){ 

 System.out.print(msg); 

 } 

}
public class ConstructorReference { 

 public static void main(String[] args) { 

 Messageable hello = Message::new; 

 hello.getMessage("Hello"); 

 } 

}

Intro to Java 8

Java has made a tremendous entry again to the software development industry after the release of Java 5. Java 8 has brought a major changes with new features that we are going to discuss in the following post. As a developer mainly focused on Java technology it is utmost important for us to learn or at least be aware of such features as the changes in the applications implementing Java 8 will be coming to you soon. I have tried to learn Java 8 and thought of sharing it to you as, like me you too have to start implementing those features in your code at least for new applications.

Java 8 has made some upgrades or new features in case of

  1. Java language
    • Lambdas and Functional Interfaces
    • Interface Default and Static Methods
    • Method References
    • Repeating annotations
    • Better Type Inference
    • Extended Annotations Support
  2. Java compiler
    • Parameter names
  3. Java libraries
    • Optional
    • Streams
    • Date/Time API (JSR 310)
    • Nashorn JavaScript engine
    • Base64
    • Parallel Arrays
    • Concurrency
  4. Java tools
    • Nashorn engine: jjs
    • Class dependency analyzer: jdeps
  5. Java runtime (JVM)

We will cover each of the topics in much simpler way so as to have a strong foundation. The following are the features brought to us by the Java folks  :-

  • Lambda expressions,

  • Method references,

  • Functional interfaces,

  • Stream API,

  • Default methods,

  • Base64 Encode Decode,

  • Static methods in interface,

  • Optional class,

  • Collectors class,

  • ForEach() method,

  • Parallel array sorting,

  • Nashorn JavaScript Engine,

  • Parallel Array Sorting,

  • Type and Repating Annotations,

  • IO Enhancements,

  • Concurrency Enhancements,

  • JDBC Enhancements etc.

 

 

Lambda and Functional Interfaces

In programming, a Lambda expression (or function) is just an anonymous function, i.e., a function with no name and without being bounded to an identifier.

The basic syntax is:

either (parameters) -> expression

or

(parameters) -> { statements; } or () -> expression

 

Java lambda expression is consisted of three components.

1) Argument-list: It can be empty or non-empty as well.

2) Arrow-token: It is used to link arguments-list and body of expression.

3) Body: It contains expressions and statements for lambda expression.

 

Why use Lambda Expression

  1. To provide the implementation of Functional interface.
  2. Less coding.

 

Rules for writing lambda expressions

  • A lambda expression can have zero, one or more parameters.
  • The type of the parameters can be explicitly declared or it can be inferred from the context.
  • Multiple parameters are enclosed in mandatory parentheses and separated by commas. Empty parentheses are used to represent an empty set of parameters.
  • When there is a single parameter, if its type is inferred, it is not mandatory to use parentheses. e.g. a -> return a*a.
  • The body of the lambda expressions can contain zero, one or more statements.
  • If body of lambda expression has single statement curly brackets are not mandatory and the return type of the anonymous function is the same as that of the body expression. When there is more than one statement in body than these must be enclosed in curly brackets.

Java was lacking functional programming as it was only a OOP language. With release of Java8 it has the feature of both functional and Object Oriented Programming.

 

What so exciting about it?

Most OOP languages evolve around objects and instances and treat only them their first class citizens. Another important entity i.e. functions take back seat. This is specially true in java, where functions can’t exist outside an object. A function itself does not mean anything in java, until it is related to some object or instance.

But in functional programming, you can define functions, give them reference variables and pass them as method arguments and much more. JavaScript is a good example of this where you can pass callback methods e.g. to Ajax calls. It’s very useful feature and has been lacking in java from beginning. Now with java 8, we can also use these lambda expressions.

(x, y) -> x + y //This function takes two parameters

//and return their sum.

Now based on type of x and y, method may be used in multiple places. Parameters can match to int, or Integer or simply String also. Based on context, it will either add two integers or concat two strings.

 

List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");

Collections.sort(names, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return b.compareTo(a);
    }
});

The static utility method Collections.sort accepts a list and a comparator in order to sort the elements of the given list. You often find yourself creating anonymous comparators and pass them to the sort method.

Instead of creating anonymous objects all day long, Java 8 comes with a much shorter syntax, lambda expressions:

Collections.sort(names, (String a, String b) -> {
    return b.compareTo(a);
});

As you can see the code is much shorter and easier to read. But it gets even shorter:

Collections.sort(names, (String a, String b) -> b.compareTo(a));

For one line method bodies you can skip both the braces {} and the return keyword. But it gets even more shorter:

Collections.sort(names, (a, b) -> b.compareTo(a));

The java compiler is aware of the parameter types so you can skip them as well. Let’s dive deeper into how lambda expressions can be used in the wild.

Let’s start with a simple example of how to sort a list of strings in prior versions of Java:
Example: – Without Lambda Expression

interface Drawable{ 

 public void draw(); 

} 

public class LambdaExpressionExample { 

 public static void main(String[] args) { 

 int width=10; 

 //without lambda, Drawable implementation using anonymous class 

 Drawable d=new Drawable(){ 

 public void draw(){System.out.println("Drawing "+width);} 

 }; 

 d.draw(); 

 } 

}

Example: – With Lambda Expression

@FunctionalInterface //It is optional 

interface Drawable{ 

 public void draw(); 

} 

public class WithLambda { 

 public static void main(String[] args) { 

 int width=10; 

 //with lambda 

 Drawable d2=()->{ 

 System.out.println("Drawing "+width); 

 }; 

 d2.draw(); 

 } 

}

Example: – Lambda Expression With No Parameter

@FunctionalInterface

interface Swimming{

 public String swim();

}

public class WithLamdaNoParam {

 public static void main(String[] args){

 Swimming swimming = () -> {

 return "I am Swimming";

 };

 System.err.println(swimming.swim());

 }

}

Example: – Lambda Expression With Single Parameter

@FunctionalInterface

interface Swimming{

 public String swim(String name);

}

public class WithLamdaSingleParam {

 public static void main(String[] args){

 Swimming swimming = (name) -> {

 return name + " is Swimming";

 };

 System.err.println(swimming.swim("Bob"));

 }

}

Example: – Lamda Expression With Multiple Parameters

@FunctionalInterface

interface Swimming{

 public String swim(String name, int age);

}

public class WithLamdaMultiParam {

 public static void main(String[] args){

 Swimming swimming = (name, age) -> {

 return name + " of " + age + " is Swimming";

 };

 System.err.println(swimming.swim("Bob", 45));

 }

}

Example: – Lambda Expression For Each Loop

import java.util.ArrayList;

@FunctionalInterface

interface Add{

 public void swim(int num1, int num2);

}

public class WithLamdaForEach {

 public static void main(String[] args){

 ArrayList<String> listOfNames = new ArrayList<String>();

 listOfNames.add("Bob");

 listOfNames.add("Matt");

 listOfNames.add("Mark");

 listOfNames.add("Kevin");

 listOfNames.forEach(

 n -> System.err.println(n)

 );

 }

}

Example: – Lambda Expression For Thread

public class WithLamdaForThread {

 public static void main(String[] args){

 //Without Lambda

 Runnable r1 = new Runnable(){

 public void run(){

 System.err.println("Thread 1 is running");

 }

 };

 Thread t1 = new Thread(r1);

 t1.start();

//With Lambda

 Runnable r2= () -> {

 System.err.println("Thread 2 is running");

 };

 Thread t2 = new Thread(r2);

 t2.start();

 }

}