Thursday 23 July 2015

Default & Static methods in Java 8


Interface: Interface is a business rules specific document/contract among various parties for effective communication between two or more interface systems.
Abstract class: Usually in Java, abstract means – incomplete. Abstract class a template, describing functionality that is common to a group of classes and require unique implementations within each class.

Prior to Java 8, Interfaces contain only “static final constants & abstract methods”. Below are the two new features introduced for Interfaces in Java 8.
Default Methods
Static Methos:

1. Default Methods:
Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

Syntax:
```java

public interface Transaction {
void insertRecord();
void updatedRecord();
void deleteRecord();
default void auditTransaction() {
// Implementation to persist information about transaction for an audit purpose
} } ```


Why do we need Default Methods in Interface?
In Java, interfaces are tightly coupled with their implementation classes. It’s not at all possible to add a new method in interface without implementing the same in its all implementers. So adding a new method in interface will break all its implementers.
So for backward compatibility, Java 8 provides a feasibility to add a new method definition an to interface.
One of the default method available in Java 8 java.util Collections’s is “forEach()”. This method is neither implemented in List nor in Collection. But, we can use this method across all List implementers.
Hierarchy:
List -> Collection -> Iterable.
So, forEach() method definition available in Iterable interface as follows:
default void forEach(Consumer action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}


Conflicts with multiple interface implementations:
When a class implements two or more interfaces and a default method with the same signature available in more than one interface, then implementer class will gets ambiguity to reuse which interface’s default method definition.
Error details:
Duplicate default methods named with the are inherited from the types and .


In this scenario, we need to override method definition in implementer class as required.
package com.sample;

public interface MetropolitonCity {

default public Integer getPropertyTaxPercent() {
return new Integer(10);
}
}
package com.sample;


public interface CapitalCity {

default public Integer getPropertyTaxPercent() {
return new Integer(8);
}
}
package com.sample;


public class Bangalore implements MetropolitonCity, CapitalCity {

public Integer getPropertyTaxPercent() {
Integer taxpercent;
// Can reuse from any one the interfaces
taxpercent = MetropolitonCity.super.getPropertyTaxPercent();
// or
taxpercent = CapitalCity.super.getPropertyTaxPercent();
// or we can add its own definition
taxpercent = new Integer(12);
return taxpercent;
}
}


Abstract class Vs Interfaces:
Once default methods introduced, both Abstract class & Interfaces looks similar. But still there is significant difference between them.

Abstract class can have constructors and member variables. Hence it can hold state of an object, whereas interfaces cannot hold the state of an object.
Methods in abstract classes can use and modify method arguments as well as the fields of their class. But default method can only access its arguments as interfaces do not have any state.
Note:
The default method cannot be final, so as to prevent modifying the default implementation of the method in the inherited classes.
The default method cannot be synchronized, while the synchronized block can be added inside the default method.
The default method cannot be used to override any non-final method of java.lang.Object class. Since Object is a super class for all classes in java, can cause confusion about its actual implementation in the sub classes.

2. Static Methods:
In general, a static method is a method that is associated with the class in which it is defined rather than with any object.
In addition to default methods, we can define static methods in Interfaces. It makes easier to organize helper methods in our library rather than keeping them in a separate utility class.
package com.sample;


public interface StaticMethodDemo {

static void staticMethod() {
System.out.println("Sample static method");
}
}
3. Functional Interfaces:
Marker Interfaces: The interfaces which contains no members in it called Marker Interfaces. Marker Interfaces are used to indicate something to Compiler, JVM.
Examples:
Java.util.Serializable : If JVM finds a class is implementing Serializable interface, it allows to persist the state of an object.
Java.lang.Clonebale: If JVM finds as a Class is implementing Clonebale interface, it performs some operation to support cloning.
The interface which contains a single abstract method is called “Functional Interface”. In Java 8, we can annotate functional interfaces with the annotation @FunctionalInterface. This annotation performs the violations at compilation time.
If an interface annotated with @FunctionalInterface and contains more/less than one abstract method, compiler throws an error as “Invalid '@FunctionalInterface' annotation; is not a functional interface”.
package com.sample;

@FunctionalInterface
public interface CapitalCity {

public abstract Integer getPropertyTaxPercent();

}
Popular Functional Interfaces in Java:
public interface Runnable { void run(); }
public interface Callable { V call() throws Exception; }
public interface ActionListener { void actionPerformed(ActionEvent e); }
public interface Comparator { int compare(T o1, T o2); boolean equals(Object obj); }
Functional interface can:
Have many number of default methods along with single abstract class. Since, default methods have already method definition.
Override public methods of java.lang.Object class and mark them as abstract. The overridden methods from Object class will not be considered as its own abstract methods.
Ex: java.util.Comporator has default, static methods and along with overridden methods from Object class. Functional interface implementation with inner class:
```java
Thread thread = new Thread(new Runnable() {

@Override
public void run() {
System.out.println(“This is a thread created with Runnable interface”);
}
});
The functional interfaces can be converted as Lambda Expressions with the following syntax.
(method arguments) -> {method body}
```
Ex:
Thread thread = new Thread(() -> System.out.println("This is a thread created with Lambda Expression"));
Comparator Interface:
public class Employee {
private Integer id;
private String name;
private Double salary;

public Employee(Integer id, String name, Double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Double getSalary() {
return salary;
}

public void setSalary(Double salary) {
this.salary = salary;
}
}

public class EmpSorting {

public void main(String[] args) {
List employees =
Arrays.asList(new Employee(1, "abc", new Double("10.00")),
new Employee(3, "def", new Double("15.00")),
new Employee(2, "ghi", new Double("5.00")));

// Sort employees list with prior to Java 8 approach
Collections.sort(employees, new Comparator() {

@Override
public int compare(Employee o1, Employee o2) {
return o1.id.compareTo(o2.id);
}
});

// Sorting employees list with Java 8 Lambda Expression
Collections.sort(employees, (Employee o1, Employee o2) -> {return o1.id.compareTo(o2.id);});
// Alos can be written as below. Here parameters datatypes can be auto detect
Collections.sort(employees, (o1, o2) -> {return o1.id.compareTo(o2.id);});
}
}

No comments:

Post a Comment