You will learn how to use default interface methods, static interface method, lambda expressions, diamond problem, method references and repeatable annotations etch. At the end of the article you will be familiar with the most recent java 8 API changes like streams, functional interfaces, map extensions and the new Date API.
1. Default Methods for Interfaces.
Java 8 enables us to add non-abstract method implementations to interfaces by using the default keyword. This feature is also known as Extension Methods.
Example of default method.
interface Java8DefaultI{abstract void hello();default void helloWorld(){System.out.println("Java8Default method calling !!");}}
Along with abstract method "hello" in Interface we have default method "helloWorld". Concrete class only need to implement the abstract method and default method will be used as it.
public class Java8Default {public static void main(String[] args) {Java8DefaultI java8Default = new Java8DefaultI() {@Overridepublic void hello() {System.out.println("Abstract method Hello Calling !!");}};java8Default.hello();java8Default.helloWorld();}}Output :Abstract method Hello Calling !! Java8Default method calling !!
2. Static Methods for Interfaces:
Java 8 enables us static method to interfaces by using the static keyword. Static Methods in Interface are those methods, which are defined in the interface with the keyword static. These static methods contain the complete definition of the function and since the definition is complete and the method is static, therefore these methods cannot be overridden or changed in the implementation class.
Example of static method : In below example define and declared the static method in interface and show here to to call this.
interface Java8StaticI{abstract void hello();static void helloWorld(){System.out.println("Java8 Static method calling !!");}}
Along with abstract method "hello" in Interface we have static method "helloWorld". Concrete class only need to implement the abstract method and static method will not be override be used as it.
public class Java8Static {public static void main(String[] args) {Java8StaticI java8Static=new Java8StaticI(){@Overridepublic void hello() {System.out.println("Hello method calling..");}};// Non-static method call by object createdjava8Static.hello();// Static method called by Interface nameJava8StaticI.helloWorld();}}// OutputHello method calling.. Java8 Static method calling !!
- 3. Functional Interfaces.
In Java 8, a functional interfaces was introduced. A so called functional interface must contain exactly one abstract method declaration. Each lambda expression of that type will be matched to this abstract method. Since default methods are not abstract you are free to add default methods to your functional interface.
@FunctionalInterface
annotation. Conceptually, a functional interface has exactly one abstract method. The compiler is aware of this annotation and throws a compiler error as soon as you try to add a second abstract method declaration to the interface.@FunctionalInterfaceinterface Java8FunctionalI<F, T>{T convert(F form);}
public class Java8Functional{public static void main(String[] args) {Java8FunctionalI<String,Integer> converter=(form)->Integer.valueOf(form);Integer intV=converter.convert("221");System.out.println(intV);}}// Output221
4. Lambda Expressions.
A basic example of the Lambda Expression is: (x,y) -> x+y;
A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
Example: Lambda expression provides implementation of functional interface. Take an example to sort the array list using The static utility method Collections.sort accept a list and comparator in order to sort the elements of the given list. Often we create the anonymous method.
import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List;public class Java8Lambda1 {public static void main(String[] args) {List<String> names = Arrays.asList("ram", "shyam", "geeta", "anita");Collections.sort(names, new Comparator<String>() {@Overridepublic int compare(String a, String b) {return a.compareTo(b);}});names.stream().forEach(System.out::println);}}
Above example of how to sort a list of strings in prior versions of Java 8
Instead of creating anonymous objects, Java 8 comes with a much shorter syntax using Lambda Expression.
Collections.sort(names,(String a, String b) ->{return a.compareTo(b);});
For one line method bodies you can skip both the braces {}
and the return
keyword. But it gets even more shorter:
Collections.sort(names,(String a, String b) ->a.compareTo(b));
The java compiler is aware of the parameter types so you can skip them as well. gets even more shorter:
Collections.sort(names,(a, b) ->a.compareTo(b));
5. Lambda Scopes:
Accessing outer scope variables from lambda expressions is very similar to anonymous objects. You can access final variables from the local outer scope as well as instance fields and static variables.
Accessing local variables: We can read final local variables from the outer scope of lambda expressions:
public class Java8LambdaScope {public static void main(String[] args) {final double pie=3.14;LambdaScope lambdaScope=(x)->pie*x*x;double area=lambdaScope.areaOfCircle(5);System.out.println(area);}}
If we don't declare variable as a final it is also valid. The variable pie implicitly final
public class Java8LambdaScope {public static void main(String[] args) {double pie=3.14; // Implicitly final variableLambdaScope lambdaScope=(x)->pie*x*x;double area=lambdaScope.areaOfCircle(5);System.out.println(area);}}
Changing the value of pie within the lambda is prohibited because the 'pie' variable is implicitly final and we can't change the value of final variable. We will get error like // variable pie is accessed from within inner class, need to be final or effectively final.
public static void main(String[] args) {double pie=3.14;LambdaScope lambdaScope1=new LambdaScope() {@Overridepublic double areaOfCircle(int radious) {// Error herepie=2.4; // variable pie is accessed from within inner class, need to be final or effectively final.return pie*radious*radious;}};}
Accessing fields and static variables: In constant to local variables we have both read and write access to instance fields and static variables from within lambda expressions. This behavior is well known from anonymous objects.
public class Java8LambdaScope {double pie=3.14;static double pie1=3.14;public static void main(String[] args) {Java8LambdaScope lambdaScope1=new Java8LambdaScope();lambdaScope1.testScope();}private void testScope() {LambdaScope lambdaScope1=new LambdaScope() {@Overridepublic double areaOfCircle(int radious) {pie=2.4;return pie*radious*radious;}};LambdaScope lambdaScope2=new LambdaScope() {@Overridepublic double areaOfCircle(int radious) {pie1=2.4;return pie*radious*radious;}};}}
Accessing Default Interface Methods: In first section we have shown how to access the default interface method.
public class Java8Default {public static void main(String[] args) {Java8DefaultI java8Default = new Java8DefaultI() {@Overridepublic void hello() {System.out.println("Abstract method Hello Calling !!");}};java8Default.hello();java8Default.helloWorld(); // default method access here}}
Note: Default methods cannot be accessed from within lambda expressions.
6. Method and Constructor References
Java 8 introducing new feature called method reference. 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. In this tutorial, we are explaining method reference concept in detail.
Types of Method References
There are following types of method references in java:
1. Reference to a static method:
public class Java8MethodStaticRef {public static void main(String[] args) {// Static method referenceDrawing drawing=Java8MethodStaticRef::drowingCircle;drawing.draw();}public static void drowingCircle(){System.out.println("Cricle Drawing");}}interface Drawing{void draw();}
public class Java8MethodConsRef {public static void main(String[] args) {// Create reference hereToUpperCase toUpperCase = new ToUpperCase();Converter<String, String> converter = toUpperCase::upperCase;String converted = converter.convert("Java");System.out.println(converted); // "JAVA"}}class ToUpperCase {String upperCase(String s) {return s.toUpperCase();}}class ToLowerCase {String lowerCase(String s) {return s.toLowerCase();}}
::
keyword works for constructors. Create new Employee class and define constructor.class Employee{String firstName;String lastName;Employee(){}Employee(String firstName,String lastName){this.firstName=firstName;this.lastName=lastName;}}
Now create the Employee factory to create the employee.
interface EmployeeFactory<P extends Employee>{P create(String firstName,String lastName);}
Without implement the EmployeeFactory method we can use this using constructor reference.
public class Java8MethodConsRef {public static void main(String[] args) {EmployeeFactory<Employee> employeeFactory=Employee::new;employeeFactory.create("Ram","Singh");}}
7: Built-in Functional Interfaces
The JDK 1.8 API contains many built-in functional interfaces. Those existing interfaces are extended to enable Lambda support via the @FunctionalInterface annotation.
Predicates
We'll combine Predicates using the methods Predicate.and(), Predicate.or(), and Predicate.negate().
import java.util.Objects;import java.util.function.Predicate;public class Java8Predicates {public static void main(String[] args) {Predicate<String> predicate1 = (s) -> s.length() > 0;Predicate<String> predicate2 = (s) -> s.length() < 5;String str="Ram";if(predicate1.and(predicate2).test(str)){System.out.println("Valid value");}// trueelse {System.out.println("Value should be greater the 0 and less then 5");}predicate1.negate().test("shyam");Predicate<Boolean> nonNull = Objects::nonNull;Predicate<Boolean> isNull = Objects::isNull;System.out.println(nonNull.test(null));Predicate<String> isEmpty = String::isEmpty;Predicate<String> isNotEmpty = isEmpty.negate();}}
Functions
Functions accept one argument and produce a result. Default methods can be used to chain multiple functions together (compose, andThen).
In below example we are concatenation of two function using andThen(). Here, x function
function gets executed and then y function
gets executed.
import java.util.function.Function;
public class Java8Function1 { public static void main(String[] args) { Function<String, String> x = myString -> myString + ",\t Indian "; Function<String, String> y = myString -> myString + ",\t Man ";
x = x.andThen(y);
System.out.println(x.apply("Hello")); }}
// OutputHello, Indian , Man
x function
function gets executed and then y function
gets executed.import java.util.function.Function;public class Java8Function1 {public static void main(String[] args) {Function<String, String> x = myString -> myString + ",\t Indian ";Function<String, String> y = myString -> myString + ",\t Man ";x = x.andThen(y);System.out.println(x.apply("Hello"));}}// OutputHello, Indian , Man
In below example we are concatenation of two function using compose method. Here, y function
composes x function
first and then executes itself.
import java.util.function.Function;
public class Java8Function1 { public static void main(String[] args) { Function<String, String> x = myString -> myString + ",\t Indian "; Function<String, String> y = myString -> myString + ",\t Man ";
x = x.compose(y);
System.out.println(x.apply("Hello")); }}
// OutputHello, Indian , Man
Thus, although outcome is same, the sequence of execution is different.
Suppliers
Suppliers produce a result of a given generic type. Unlike Functions, Suppliers don’t accept arguments.
import java.time.LocalDateTime;import java.util.function.Supplier;
public class Java8Supplier {
public static void main(String[] args) { Supplier<Employee> employeeSupplier = Employee::new; employeeSupplier.get(); // Create new employee
Supplier<LocalDateTime> s = () -> LocalDateTime.now(); LocalDateTime time = s.get();
System.out.println(time);
}}
import java.time.LocalDateTime;import java.util.function.Supplier;public class Java8Supplier {public static void main(String[] args) {Supplier<Employee> employeeSupplier = Employee::new;employeeSupplier.get(); // Create new employeeSupplier<LocalDateTime> s = () -> LocalDateTime.now();LocalDateTime time = s.get();System.out.println(time);}}
Consumers
Consumers represents operations to be performed on a single input argument.
import java.util.function.Consumer;
public class Java8Consumer { public static void main(String[] args) { Consumer<Employee> greeter = (p) -> System.out.println("Hello, " + p.firstName); greeter.accept(new Employee("Ram", "Singh")); }}
import java.util.function.Consumer;public class Java8Consumer {public static void main(String[] args) {Consumer<Employee> greeter = (p) -> System.out.println("Hello, " + p.firstName);greeter.accept(new Employee("Ram", "Singh"));}}
Comparators
Comparators are well known from older versions of Java. Java 8 adds various default methods to the interface.
import java.util.ArrayList;import java.util.Comparator;import java.util.List;
public class Java8Comparator { public static void main(String[] args) { List<Employee> employeeList=new ArrayList<>(); ini(employeeList);
employeeList.sort(Comparator.comparing(Employee::getFirstName). thenComparing(Employee::getLastName)); System.out.println(employeeList.toString());
}
private static void ini(List<Employee> employeeList) { employeeList.add(new Employee("Ram","Singh")); employeeList.add(new Employee("Shyam","Singh")); employeeList.add(new Employee("Jeevan","Ram")); employeeList.add(new Employee("Radhey","Shyam")); employeeList.add(new Employee("Ram","Pyare")); }
}
import java.util.ArrayList;import java.util.Comparator;import java.util.List;public class Java8Comparator {public static void main(String[] args) {List<Employee> employeeList=new ArrayList<>();ini(employeeList);employeeList.sort(Comparator.comparing(Employee::getFirstName).thenComparing(Employee::getLastName));System.out.println(employeeList.toString());}private static void ini(List<Employee> employeeList) {employeeList.add(new Employee("Ram","Singh"));employeeList.add(new Employee("Shyam","Singh"));employeeList.add(new Employee("Jeevan","Ram"));employeeList.add(new Employee("Radhey","Shyam"));employeeList.add(new Employee("Ram","Pyare"));}}
No comments:
Post a Comment