Sunday, November 15, 2015

Exceptional Handling in Java

An exception (or exceptional event) is a problem that arises during the execution of a program. When an Exception occurs the normal flow of the program is disrupted and the program/Application terminates abnormally, which is not recommended, therefore these exceptions are to be handled.

An exception can occur for many different reasons, below given are some scenarios where exception occurs.

    A user has entered invalid data.
    A file that needs to be opened cannot be found.
    A network connection has been lost in the middle of communications or the JVM has run out of memory.
   
Some of these exceptions are caused by user error, others by programmer error, and others by physical resources that have failed in some manner.
Based on these we have three categories of Exceptions you need to understand them to know how exception handling works in Java,

    Checked exceptions: A checked exception is an exception that occurs at the compile time, these are also called as compile time exceptions. These exceptions cannot simply be ignored at the time of compilation, the Programmer should take care of (handle) these exceptions.

    For example, if you use FileReader class in your program to read data from a file, if the file specified in its constructor doesn't exist, then an FileNotFoundException occurs, and compiler prompts the programmer to handle the exception.

import java.io.File;
import java.io.FileReader;

public class FilenotFound {

   public static void main(String args[]){       
      File file=new File("C://file.txt");
      FileReader fr = new FileReader(file);
   }
  
}

If you try to compile the above program you will get exceptions as shown below.

FilenotFound.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
      FileReader fr = new FileReader(file);
                      ^
1 error

Since the methods read() and close() of FileReader class throws IOException, you can observe that compiler notifies to handle IOException, along with FileNotFoundException.
  • Unchecked exceptions: An Unchecked exception is an exception that occurs at the time of execution, these are also called as Runtime Exceptions, these include programming bugs, such as logic errors or improper use of an API. runtime exceptions are ignored at the time of compilation.
    For example, if you have declared an array of size 5 in your program, and trying to call the 6th element of the array then an ArrayIndexOutOfBoundsExceptionexception occurs.
public class Unchecked {
  
   public static void main(String args[]){
      int num[]={1,2,3,4};
      System.out.println(num[5]);
   }
}

If you compile and execute the above program you will get exception as shown below.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at Exceptions.Unchecked.main(Unchecked_Demo.java:8)


Errors: These are not exceptions at all, but problems that arise beyond the control
 of the user or the programmer. Errors are typically ignored in your code because 
you can rarely do anything about an error. For example, if a stack overflow occurs,
an error will arise. They are also ignored at the time of compilation. 


Exception Hierarchy:

All exception classes are subtypes of the java.lang.Exception class. The exception class is a subclass of the Throwable class. Other than the exception class there is another subclass called Error which is derived from the Throwable class.
Errors are not normally trapped form the Java programs. These conditions normally happen in case of severe failures, which are not handled by the java programs. Errors are generated to indicate errors generated by the runtime environment. Example : JVM is out of Memory. Normally programs cannot recover from errors.
The Exception class has two main subclasses: IOException class and RuntimeException Class.







Exceptions Methods:

Following is the list of important medthods available in the Throwable class.

public String getMessage()
Returns a detailed message about the exception that has occurred. This message is initialized in the Throwable constructor.
    
public Throwable getCause()
Returns the cause of the exception as represented by a Throwable object.
    
public String toString()
Returns the name of the class concatenated with the result of getMessage()

public void printStackTrace()

Prints the result of toString() along with the stack trace to System.err, the error output stream.
    
public StackTraceElement [] getStackTrace()
Returns an array containing each element on the stack trace. The element at index 0 represents the top of the call stack, and the last element in the array represents the method at the bottom of the call stack.
    
public Throwable fillInStackTrace()
Fills the stack trace of this Throwable object with the current stack trace, adding to any previous information in the stack trace.





Catching Exceptions:

A method catches an exception using a combination of the try and catch keywords. A try/catch block is placed around the code that might generate an exception. Code within a try/catch block is referred to as protected code, and the syntax for using try/catch as
try
{
   //Protected code
}catch(ExceptionName e1)
{
   //Catch block
}
The code which is prone to exceptions is placed in the try block, when an exception occurs, that exception occurred is handled by catch block associated with it. Every try block should be immediately followed either by a class block or finally block.
A catch statement involves declaring the type of exception you are trying to catch. If an exception occurs in protected code, the catch block (or blocks) that follows the try is checked. If the type of exception that occurred is listed in a catch block, the exception is passed to the catch block much as an argument is passed into a method parameter.

Example:

The following is an array is declared with 2 elements. Then the code tries to access the 3rd element of the array which throws an exception.
// File Name : ExcepTest.java
import java.io.*;
public class ExcepTest{

   public static void main(String args[]){
      try{
         int a[] = new int[2];
         System.out.println("Access element three :" + a[3]);
      }catch(ArrayIndexOutOfBoundsException e){
         System.out.println("Exception thrown  :" + e);
      }
      System.out.println("Out of the block");
   }
}
This would produce the following result:
Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block

Multiple catch Blocks:

A try block can be followed by multiple catch blocks. The syntax for multiple catch blocks looks like the following:
try
{
   //Protected code
}catch(ExceptionType1 e1)
{
   //Catch block
}catch(ExceptionType2 e2)
{
   //Catch block
}catch(ExceptionType3 e3)
{
   //Catch block
}
The previous statements demonstrate three catch blocks, but you can have any number of them after a single try. If an exception occurs in the protected code, the exception is thrown to the first catch block in the list. If the data type of the exception thrown matches ExceptionType1, it gets caught there. If not, the exception passes down to the second catch statement. This continues until the exception either is caught or falls through all catches, in which case the current method stops execution and the exception is thrown down to the previous method on the call stack.

Example:

Here is code segment showing how to use multiple try/catch statements.
try
{
   file = new FileInputStream(fileName);
   x = (byte) file.read();
}catch(IOException i)
{
   i.printStackTrace();
   return -1;
}catch(FileNotFoundException f) //Not valid!
{
   f.printStackTrace();
   return -1;
}

Catching multiple type of exceptions

Since Java 7 you can handle more than one exceptions using a single catch block, this feature simplifies the code. Below given is the syntax of writing
catch (IOException|FileNotFoundException ex) {
   logger.log(ex);
   throw ex;

The throws/throw Keywords:

If a method does not handle a checked exception, the method must declare it using the throws keyword. The throws keyword appears at the end of a method's signature.
You can throw an exception, either a newly instantiated one or an exception that you just caught, by using the throw keyword.
Try to understand the difference between throws and throw keywords, throws is used to postpone the handling of a checked exception and throw is used to invoke an exception explicitly. The following method declares that it throws a RemoteException:
import java.io.*;
public class className
{
   public void deposit(double amount) throws RemoteException
   {
      // Method implementation
      throw new RemoteException();
   }
   //Remainder of class definition
}
A method can declare that it throws more than one exception, in which case the exceptions are declared in a list separated by commas. For example, the following method declares that it throws a RemoteException and an InsufficientFundsException:
import java.io.*;
public class className
{
   public void withdraw(double amount) throws RemoteException,
                              InsufficientFundsException
   {
       // Method implementation
   }
   //Remainder of class definition
}

The finally block

The finally block follows a try block or a catch block. A finally block of code always executes, irrespective of occurrence of an Exception.
Using a finally block allows you to run any cleanup-type statements that you want to execute, no matter what happens in the protected code.
A finally block appears at the end of the catch blocks and has the following syntax:
try
{
   //Protected code
}catch(ExceptionType1 e1)
{
   //Catch block
}catch(ExceptionType2 e2)
{
   //Catch block
}catch(ExceptionType3 e3)
{
   //Catch block
}finally
{
   //The finally block always executes.
}

Example:

public class ExcepTest{

   public static void main(String args[]){
      int a[] = new int[2];
      try{
         System.out.println("Access element three :" + a[3]);
      }catch(ArrayIndexOutOfBoundsException e){
         System.out.println("Exception thrown  :" + e);
      }
      finally{
         a[0] = 6;
         System.out.println("First element value: " +a[0]);
         System.out.println("The finally statement is executed");
      }
   }
}
This would produce the following result:
Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
First element value: 6
The finally statement is executed
Note the following:
  • A catch clause cannot exist without a try statement.
  • It is not compulsory to have finally clauses when ever a try/catch block is present.
  • The try block cannot be present without either catch clause or finally clause.
  • Any code cannot be present in between the try, catch, finally blocks.

The try-with-resources

Generally when we use any resources like streams, connections etc.. we have to close them explicitly using finally block. In the program given below we are reading data from a file using FileReader and we are closing it using finally block.
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

   public static void main(String args[]){
      FileReader fr=null;  
      try{
         File file=new File("file.txt");
         fr = new FileReader(file);  char [] a = new char[50];
         fr.read(a); // reads the content to the array
         for(char c : a)
         System.out.print(c); //prints the characters one by one
      }catch(IOException e){
          e.printStackTrace();
       }
       finally{ 
          try{
              fr.close();
          }catch(IOException ex){  
               ex.printStackTrace();
           }
       }
    }

}
try-with-resources, also referred as automatic resource management. is a new exception handling mechanism that was introduced in Java7, which automatically closes the resources used within the try catch block.
To use this statement you simply need to declare the required resources within the parenthesis, the created resource will be closed automatically at the end of the block, below given is the syntax of try-with-resources statement.
try(FileReader fr=new FileReader("file path"))
   {
   //use the resource
   }catch(){
      //body of catch 
    }
   }
Below given is the program that reads the data in a file using try-with-resources statement.
import java.io.FileReader;
import java.io.IOException;

public class Try_withDemo {

   public static void main(String args[]){
        
      try(FileReader fr=new FileReader("E://file.txt")){
         char [] a = new char[50];
         fr.read(a); // reads the contentto the array
         for(char c : a)
         System.out.print(c); //prints the characters one by one
      }catch(IOException e){
          e.printStackTrace();
       }   
   }
}
Following points are to be kept in mind while working with try-with resources statement.
  • To use a class with try-with-resources statement it should implement AutoCloseable interface and the close() method of it gets invoked automatically at runtime.
  • You can declare more than one class in try-with-resources statement.
  • while you declare multiple classes in the try block of try-with-resources statement these classes are closed in reverse order.
  • Except the deceleration of resources within the parenthesis every thing is same as normal try/catch block of a try block.
  • The resource declared in try gets instantiated just before the start of the try-block.
  • The resource declared at the try block is implicitly declared as final.

User-defined Exceptions:

You can create your own exceptions in Java. Keep the following points in mind when writing your own exception classes:
  • All exceptions must be a child of Throwable.
  • If you want to write a checked exception that is automatically enforced by the Handle or Declare Rule, you need to extend the Exception class.
  • If you want to write a runtime exception, you need to extend the RuntimeException class.
We can define our own Exception class as below:
class MyException extends Exception{
}
You just need to extend the predefined Exception class to create your own Exception. These are considered to be checked exceptions. The following InsufficientFundsException class is a user-defined exception that extends the Exception class, making it a checked exception. An exception class is like any other class, containing useful fields and methods.

Example:

// File Name InsufficientFundsException.java
import java.io.*;

public class InsufficientFundsException extends Exception
{
   private double amount;
   public InsufficientFundsException(double amount)
   {
      this.amount = amount;
   } 
   public double getAmount()
   {
      return amount;
   }
}
To demonstrate using our user-defined exception, the following CheckingAccount class contains a withdraw() method that throws an InsufficientFundsException.
// File Name CheckingAccount.java
import java.io.*;

public class CheckingAccount
{
   private double balance;
   private int number;
   
   public CheckingAccount(int number)
   {
      this.number = number;
   }
   
   public void deposit(double amount)
   {
      balance += amount;
   }
   
   public void withdraw(double amount) throws InsufficientFundsException
   {
      if(amount <= balance)
      {
         balance -= amount;
      }
      else
      {
         double needs = amount - balance;
         throw new InsufficientFundsException(needs);
      }
   }
   
   public double getBalance()
   {
      return balance;
   }
   
   public int getNumber()
   {
      return number;
   }
}
The following BankDemo program demonstrates invoking the deposit() and withdraw() methods of CheckingAccount.
// File Name BankDemo.java
public class BankDemo
{
   public static void main(String [] args)
   {
      CheckingAccount c = new CheckingAccount(101);
      System.out.println("Depositing $500...");
      c.deposit(500.00);
      
      try
      {
         System.out.println("\nWithdrawing $100...");
         c.withdraw(100.00);
         System.out.println("\nWithdrawing $600...");
         c.withdraw(600.00);
      }catch(InsufficientFundsException e)
      {
         System.out.println("Sorry, but you are short $" + e.getAmount());
         e.printStackTrace();
      }
    }
}
Compile all the above three files and run BankDemo, this would produce the following result:
Depositing $500...

Withdrawing $100...

Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsException
        at CheckingAccount.withdraw(CheckingAccount.java:25)
        at BankDemo.main(BankDemo.java:13)

Common Exceptions:

In Java, it is possible to define two catergories of Exceptions and Errors.
  • JVM Exceptions: - These are exceptions/errors that are exclusively or logically thrown by the JVM. Examples : NullPointerException, ArrayIndexOutOfBoundsException, ClassCastException,
  • Programmatic exceptions: - These exceptions are thrown explicitly by the application or the API programmers Examples: IllegalArgumentException, IllegalStateException.


Read More 

Java 7 features
How to Reset Arraylist In Java
How HashMap Work in Java
Why wait (), notify () and notifyAll () must be called from synchronized block or method in Java
XPath to locate Information in XML
Internals of Garbage Collector
Reference Type in Java
Different Ways to Create ObjectClass Loaders in Java
Producer Consumer Problem
Why String is Final in Java
Singleton Class using Enum
JSON tutorial

Java 8 Features

JAVA 8 (aka jdk 1.8) is a major release of JAVA programming language development. Its initial version was released on 18 March 2014. With the Java 8 release, Java provided support for functional programming, new JavaScript engine, new APIs for date time manipulation, new streaming API, etc.

There are dozens of features added to Java 8, the most significant ones are mentioned below

1) Lambda expression − Adds functional processing capability to Java.
2) Method references − Referencing functions by their names instead of invoking them directly.   Using   functions as parameter.
3) Default method − Interface to have default method implementation.
4) New tools − New compiler tools and utilities are added like ‘jdeps’ to figure out dependencies.
5) Stream API − New stream API to facilitate pipeline processing.
6) Date Time API − Improved date time API.
7) Optional − Emphasis on best practices to handle null values properly.
8) Nashorn, JavaScript Engine − A Java-based engine to execute JavaScript code.

Along with these new featuers, lots of feature enhancements are done under-the-hood, at both compiler and JVM level.

Programming Style

Java 8 is expected to change the way programmers code their programs. For a brief comparison between Java 7 and Java 8, let us see a sorting program written with both Java 7 and Java 8 syntaxes.



import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;

public class Java8Tester {
   public static void main(String args[]){
  
      List names1 = new ArrayList();
      names1.add("Raj ");
      names1.add("James ");
      names1.add("Andrew ");
      names1.add("Sachin ");
      names1.add("Dhoni ");
       
      List names2 = new ArrayList();
      names2.add("Raj ");
      names2.add("James ");
      names2.add("Andrew ");
      names2.add("Sachin ");
      names2.add("Dhoni ");;
       
      Java8Tester tester = new Java8Tester();
      System.out.println("Sort using Java 7 syntax: ");
       
      tester.sortUsingJava7(names1);
      System.out.println(names1);
      System.out.println("Sort using Java 8 syntax: ");
       
      tester.sortUsingJava8(names2);
      System.out.println(names2);
   }
  
   //sort using java 7
   private void sortUsingJava7(List names){  
      Collections.sort(names, new Comparator() {
         @Override
         public int compare(String s1, String s2) {
            return s1.compareTo(s2);
         }
      });
   }
  
   //sort using java 8
   private void sortUsingJava8(List names){
      Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
   }
}

This program should yield the following output −

Sort using Java 7 syntax:
[ Andrew Dhoni James Raj Sachin ]
Sort using Java 8 syntax:
[ Andrew Dhoni James Raj Sachin ]



Lambda expressions

Lambda expressions are introduced in Java 8 and are touted to be the biggest feature of Java 8. Lambda expression facilitates functional programming, and simplifies the development a lot.
Syntax

A lambda expression is characterized by the following syntax −
parameter -> expression body

Following are the important characteristics of a lambda expression −

    Optional type declaration − No need to declare the type of a parameter. The compiler can inference the same from the value of the parameter.

    Optional parenthesis around parameter − No need to declare a single parameter in parenthesis. For multiple parameters, parentheses are required.

    Optional curly braces − No need to use curly braces in expression body if the body contains a single statement.

    Optional return keyword − The compiler automatically returns the value if the body has a single expression to return the value. Curly braces are required to indicate that expression returns a value.


Lambda Expressions Example

Create the following Java program using editor and save in some folder like C:\>JAVA.
Java8Tester.java

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
       
      //with type declaration
      MathOperation addition = (int a, int b) -> a + b;
       
      //with out type declaration
      MathOperation subtraction = (a, b) -> a - b;
       
      //with return statement along with curly braces
      MathOperation multiplication = (int a, int b) -> { return a * b; };
       
      //without return statement and without curly braces
      MathOperation division = (int a, int b) -> a / b;
       
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
       
      //with parenthesis
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
       
      //without parenthesis
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
       
      greetService1.sayMessage("Mahesh");
      greetService2.sayMessage("Suresh");
   }
   
   interface MathOperation {
      int operation(int a, int b);
   }
   
   interface GreetingService {
      void sayMessage(String message);
   }
   
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}


Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Mahesh
Hello Suresh

Following are the important points to be considered in the above example.

    Lambda expressions are used primarily to define inline implementation of a functional interface, i.e., an interface with a single method only. In the above example, we've used various types of lambda expressions to define the operation method of MathOperation interface. Then we have defined the implementation of sayMessage of GreetingService.

    Lambda expression eliminates the need of anonymous class and gives a very simple yet powerful functional programming capability to Java.

Scope

Using lambda expression, you can refer to final variable or effectively final variable (which is assigned only once). Lambda expression throws a compilation error, if a variable is assigned a value the second time.
Scope Example

Create the following Java program using editor and save in some folder like C:\>JAVA.

Java8Tester.java

public class Java8Tester {

   final static String salutation = "Hello! ";
  
   public static void main(String args[]){
      GreetingService greetService1 = message ->
      System.out.println(salutation + message);
      greetService1.sayMessage("Mahesh");
   }
   
   interface GreetingService {
      void sayMessage(String message);
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −
Hello! Mahesh


Method References
Method references help to point to methods by their names. A method reference is described using :: (double colon) symbol. A method reference can be used to point the following types of methods −

    Static methods
    Instance methods
    Constructors using new operator (TreeSet::new)

Method Reference Example

Let's look into an example of method referencing to get a more clear picture. Write the following program in an code editor and match the results.
Java8Tester.java

import java.util.List;
import java.util.ArrayList;

public class Java8Tester {
   public static void main(String args[]){
      List names = new ArrayList();
       
      names.add("Mahesh");
      names.add("Suresh");
      names.add("Ramesh");
      names.add("Naresh");
      names.add("Kalpesh");
       
      names.forEach(System.out::println);
   }
}

Here we have passed System.out::println method as a static method reference.
Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

Mahesh
Suresh
Ramesh
Naresh
Kalpesh


Functional Interfaces

Functional interfaces have a single functionality to exhibit. For example, a Comparable interface with a single method ‘compareTo’ is used for comparison purpose. Java 8 has defined a lot of functional interfaces to be used extensively in lambda expressions. Following is the list of functional interfaces defined in java.util.Function package.


Interface & Description

1) BiConsumer
Represents an operation that accepts two input arguments, and returns no result.

2) BiFunction

Represents a function that accepts two arguments and produces a result.

3) BinaryOperator

Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
 

4) BiPredicate
Represents a predicate (Boolean-valued function) of two arguments.


5) BooleanSupplier

Represents a supplier of Boolean-valued results.

6 ) Consumer
Represents an operation that accepts a single input argument and returns no result.
 

7) DoubleBinaryOperator
Represents an operation upon two double-valued operands and producing a double-valued result.
 

8)  DoubleConsumer
Represents an operation that accepts a single double-valued argument and returns no result.


9) DoubleFunction
Represents a function that accepts a double-valued argument and produces a result.
 

10) DoublePredicate
Represents a predicate (Boolean-valued function) of one double-valued argument.
 

11) DoubleSupplier
Represents a supplier of double-valued results.


12) DoubleToIntFunction
Represents a function that accepts a double-valued argument and produces an int-valued result.
 

13) DoubleToLongFunction
Represents a function that accepts a double-valued argument and produces a long-valued result.
 

14) DoubleUnaryOperator
Represents an operation on a single double-valued operand that produces a double-valued result.


15) Function
Represents a function that accepts one argument and produces a result.
 

16) IntBinaryOperator
Represents an operation upon two int-valued operands and produces an int-valued result.


17) IntConsumer
Represents an operation that accepts a single int-valued argument and returns no result.


18) IntFunction
Represents a function that accepts an int-valued argument and produces a result.


19) IntPredicate
Represents a predicate (Boolean-valued function) of one int-valued argument.


20) IntSupplier
Represents a supplier of int-valued results.


21) IntToDoubleFunction
Represents a function that accepts an int-valued argument and produces a double-valued result.


22) IntToLongFunction
Represents a function that accepts an int-valued argument and produces a long-valued result.


23) IntUnaryOperator
Represents an operation on a single int-valued operand that produces an int-valued result.


24) LongBinaryOperator
Represents an operation upon two long-valued operands and produces a long-valued result.


25) LongConsumer
Represents an operation that accepts a single long-valued argument and returns no result.


26) LongFunction
Represents a function that accepts a long-valued argument and produces a result.


27) LongPredicate
Represents a predicate (Boolean-valued function) of one long-valued argument.
 

28) LongSupplier
Represents a supplier of long-valued results.


29) LongToDoubleFunction
Represents a function that accepts a long-valued argument and produces a double-valued result.


30) LongToIntFunction
Represents a function that accepts a long-valued argument and produces an int-valued result.
 

31) LongUnaryOperator
Represents an operation on a single long-valued operand that produces a long-valued result.
 

32) ObjDoubleConsumer
Represents an operation that accepts an object-valued and a double-valued argument, and returns no result.


33) ObjIntConsumer
Represents an operation that accepts an object-valued and an int-valued argument, and returns no result.


34) ObjLongConsumer
Represents an operation that accepts an object-valued and a long-valued argument, and returns no result.


35) Predicate
Represents a predicate (Boolean-valued function) of one argument.
 

36) Supplier
Represents a supplier of results.


37) ToDoubleBiFunction
Represents a function that accepts two arguments and produces a double-valued result.
 

38) ToDoubleFunction
Represents a function that produces a double-valued result.
 

39) ToIntBiFunction
Represents a function that accepts two arguments and produces an int-valued result.
 

40) ToIntFunction
Represents a function that produces an int-valued result.
 

41) ToLongBiFunction
Represents a function that accepts two arguments and produces a long-valued result.
 

42) ToLongFunction
Represents a function that produces a long-valued result.


43) UnaryOperator
Represents an operation on a single operand that produces a result of the same type as its operand.
 

Functional Interface Example
Predicate interface is a functional interface with a method test(Object) to return a Boolean value. This interface signifies that an object is tested to be true or false.

To get more clarity on this, write the following program in an code editor and verify the results.
Java8Tester.java

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Java8Tester {
   public static void main(String args[]){
      List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
       
      // Predicate predicate = n -> true
      // n is passed as parameter to test method of Predicate interface
      // test method will always return true no matter what value n has.
       
      System.out.println("Print all numbers:");
       
      //pass n as parameter
      eval(list, n->true);
       
      // Predicate predicate1 = n -> n%2 == 0
      // n is passed as parameter to test method of Predicate interface
      // test method will return true if n%2 comes to be zero
       
      System.out.println("Print even numbers:");
      eval(list, n-> n%2 == 0 );
       
      // Predicate predicate2 = n -> n > 3
      // n is passed as parameter to test method of Predicate interface
      // test method will return true if n is greater than 3.
       
      System.out.println("Print numbers greater than 3:");
      eval(list, n-> n > 3 );
   }
   
   public static void eval(List list, Predicate predicate) {
      for(Integer n: list) {
       
         if(predicate.test(n)) {
            System.out.println(n + " ");
         }
      }
   }
}

Here we've passed Predicate interface, which takes a single input and returns Boolean.
Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

Print all numbers:
1
2
3
4
5
6
7
8
9
Print even numbers:
2
4
6
8
Print numbers greater than 3:
4
5
6
7
8
9


Default Methods
Java 8 introduces a new concept of default method implementation in interfaces. This capability is added for backward compatibility so that old interfaces can be used to leverage the lambda expression capability of Java 8. For example, ‘List’ or ‘Collection’ interfaces do not have ‘forEach’ method declaration. Thus, adding such method will simply break the collection framework implementations. Java 8 introduces default method so that List/Collection interface can have a default implementation of forEach method, and the class implementing these interfaces need not implement the same.
 

Syntax

public interface vehicle {
   default void print(){
      System.out.println("I am a vehicle!");
   }
}

Multiple Defaults

With default functions in interfaces, there is a possibility that a class is implementing two interfaces with same default methods. The following code explains how this ambiguity can be resolved.

public interface vehicle {
   default void print(){
      System.out.println("I am a vehicle!");
   }
}

public interface fourWheeler {
   default void print(){
      System.out.println("I am a four wheeler!");
   }
}

First solution is to create an own method that overrides the default implementation.
public class car implements vehicle, fourWheeler {
   default void print(){
      System.out.println("I am a four wheeler car vehicle!");
   }
}

Second solution is to call the default method of the specified interface using super.

public class car implements vehicle, fourWheeler {
   default void print(){
      vehicle.super.print();
   }
}

Static Default Methods
An interface can also have static helper methods from Java 8 onwards.

public interface vehicle {
   default void print(){
      System.out.println("I am a vehicle!");
   }
   
   static void blowHorn(){
      System.out.println("Blowing horn!!!");
   }
}

Default Method Example

Let's see an example to get more clarity on default method. Please write the following program in an code editor, understand and verify the results.
Java8Tester.java

public class Java8Tester {
   public static void main(String args[]){
      Vehicle vehicle = new Car();
      vehicle.print();
   }
}

interface Vehicle {
   default void print(){
      System.out.println("I am a vehicle!");
   }
   
   static void blowHorn(){
      System.out.println("Blowing horn!!!");
   }
}

interface FourWheeler {
   default void print(){
      System.out.println("I am a four wheeler!");
   }
}

class Car implements Vehicle, FourWheeler {
   public void print(){
      Vehicle.super.print();
      FourWheeler.super.print();
      Vehicle.blowHorn();
      System.out.println("I am a car!");
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

I am a vehicle!
I am a four wheeler!
Blowing horn!!!
I am a car!


Streams
Stream is a new abstract layer introduced in Java 8. Using stream, you can process data in a declarative way similar to SQL statements. For example, consider the following SQL statement −

SELECT max(salary), employee_id, employee_name FROM Employee

The above SQL expression automatically returns the maximum salaried employee's details, without doing any computation on the developer's end. Using collections framework in Java, a developer has to use loops and make repeated checks. Another concern is efficiency; as multi-core processors are available at ease, a Java developer has to write parallel code processing that can be pretty error-prone.

To resolve such issues, Java 8 introduced the concept of stream that lets the developer to process data declaratively and leverage multicore architecture without the need to write any specific code for it.

What is Stream?
Stream represents a sequence of objects from a source, which supports aggregate operations. Following are the characteristics of a Stream −

    Sequence of elements − A stream provides a set of elements of specific type in a sequential manner. A stream gets/computes elements on demand. It never stores the elements.

    Source − Stream takes Collections, Arrays, or I/O resources as input source.

    Aggregate operations − Stream supports aggregate operations like filter, map, limit, reduce, find, match, and so on.

    Pipelining − Most of the stream operations return stream itself so that their result can be pipelined. These operations are called intermediate operations and their function is to take input, process them, and return output to the target. collect() method is a terminal operation which is normally present at the end of the pipelining operation to mark the end of the stream.

    Automatic iterations − Stream operations do the iterations internally over the source elements   provided, in contrast to Collections where explicit iteration is required.

   Generating Streams
   With Java 8, Collection interface has two methods to generate a Stream −

    stream() − Returns a sequential stream considering collection as its source.

    parallelStream() − Returns a parallel Stream considering collection as its source.

List strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

forEach
Stream has provided a new method ‘forEach’ to iterate each element of the stream. The following code segment shows how to print 10 random numbers using forEach.

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

map
The ‘map’ method is used to map each element to its corresponding result. The following code segment prints unique squares of numbers using map.

List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
//get list of unique squares
List squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

filter
The ‘filter’ method is used to eliminate elements based on a criteria. The following code segment prints a count of empty strings using filter.

Liststrings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//get count of empty string
int count = strings.stream().filter(string -> string.isEmpty()).count();

limit
The ‘limit’ method is used to reduce the size of the stream. The following code segment shows how to print 10 random numbers using limit.

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

sorted
The ‘sorted’ method is used to sort the stream. The following code segment shows how to print 10 random numbers in a sorted order.

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

Parallel Processing
parallelStream is the alternative of stream for parallel processing. Take a look at the following code segment that prints a count of empty strings using parallelStream.

List strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//get count of empty string
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();

It is very easy to switch between sequential and parallel streams.
Collectors

Collectors are used to combine the result of processing on the elements of a stream. Collectors can be used to return a list or a string.

Liststrings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("Filtered List: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);

Statistics
With Java 8, statistics collectors are introduced to calculate all statistics when stream processing is being done.

List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Highest number in List : " + stats.getMax());
System.out.println("Lowest number in List : " + stats.getMin());
System.out.println("Sum of all numbers : " + stats.getSum());
System.out.println("Average of all numbers : " + stats.getAverage());

Stream Example
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java

import java.util.ArrayList;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.Map;

public class Java8Tester {
   public static void main(String args[]){
      System.out.println("Using Java 7: ");
       
      // Count empty strings
      List strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
      System.out.println("List: " +strings);
      long count = getCountEmptyStringUsingJava7(strings);
       
      System.out.println("Empty Strings: " + count);
      count = getCountLength3UsingJava7(strings);
       
      System.out.println("Strings of length 3: " + count);
       
      //Eliminate empty string
      List filtered = deleteEmptyStringsUsingJava7(strings);
      System.out.println("Filtered List: " + filtered);
       
      //Eliminate empty string and join using comma.
      String mergedString = getMergedStringUsingJava7(strings,", ");
      System.out.println("Merged String: " + mergedString);
      List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
       
      //get list of square of distinct numbers
      List squaresList = getSquares(numbers);
      System.out.println("Squares List: " + squaresList);
      List integers = Arrays.asList(1,2,13,4,15,6,17,8,19);
       
      System.out.println("List: " +integers);
      System.out.println("Highest number in List : " + getMax(integers));
      System.out.println("Lowest number in List : " + getMin(integers));
      System.out.println("Sum of all numbers : " + getSum(integers));
      System.out.println("Average of all numbers : " + getAverage(integers));
      System.out.println("Random Numbers: ");
       
      //print ten random numbers
      Random random = new Random();
       
      for(int i=0; i < 10; i++){
         System.out.println(random.nextInt());
      }
       
      System.out.println("Using Java 8: ");
      System.out.println("List: " +strings);
       
      count = strings.stream().filter(string->string.isEmpty()).count();
      System.out.println("Empty Strings: " + count);
       
      count = strings.stream().filter(string -> string.length() == 3).count();
      System.out.println("Strings of length 3: " + count);
       
      filtered = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.toList());
      System.out.println("Filtered List: " + filtered);
       
      mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", "));
      System.out.println("Merged String: " + mergedString);
       
      squaresList = numbers.stream().map( i ->i*i).distinct().collect(Collectors.toList());
      System.out.println("Squares List: " + squaresList);
      System.out.println("List: " +integers);
       
      IntSummaryStatistics stats = integers.stream().mapToInt((x) ->x).summaryStatistics();
       
      System.out.println("Highest number in List : " + stats.getMax());
      System.out.println("Lowest number in List : " + stats.getMin());
      System.out.println("Sum of all numbers : " + stats.getSum());
      System.out.println("Average of all numbers : " + stats.getAverage());
      System.out.println("Random Numbers: ");
       
      random.ints().limit(10).sorted().forEach(System.out::println);
       
      //parallel processing
      count = strings.parallelStream().filter(string -> string.isEmpty()).count();
      System.out.println("Empty Strings: " + count);
   }
   
   private static int getCountEmptyStringUsingJava7(List strings){
      int count = 0;
       
      for(String string: strings){
       
         if(string.isEmpty()){
            count++;
         }
      }
      return count;
   }
   
   private static int getCountLength3UsingJava7(List strings){
      int count = 0;
       
      for(String string: strings){
       
         if(string.length() == 3){
            count++;
         }
      }
      return count;
   }
   
   private static List deleteEmptyStringsUsingJava7(List strings){
      List filteredList = new ArrayList();
       
      for(String string: strings){
       
         if(!string.isEmpty()){
             filteredList.add(string);
         }
      }
      return filteredList;
   }
   
   private static String getMergedStringUsingJava7(List strings, String separator){
      StringBuilder stringBuilder = new StringBuilder();
       
      for(String string: strings){
       
         if(!string.isEmpty()){
            stringBuilder.append(string);
            stringBuilder.append(separator);
         }
      }
      String mergedString = stringBuilder.toString();
      return mergedString.substring(0, mergedString.length()-2);
   }
   
   private static List getSquares(List numbers){
      List squaresList = new ArrayList();
       
      for(Integer number: numbers){
         Integer square = new Integer(number.intValue() * number.intValue());
           
         if(!squaresList.contains(square)){
            squaresList.add(square);
         }
      }
      return squaresList;
   }
   
   private static int getMax(List numbers){
      int max = numbers.get(0);
       
      for(int i=1;i < numbers.size();i++){
       
         Integer number = numbers.get(i);
           
         if(number.intValue() > max){
            max = number.intValue();
         }
      }
      return max;
   }
   
   private static int getMin(List numbers){
      int min = numbers.get(0);
       
      for(int i=1;i < numbers.size();i++){
         Integer number = numbers.get(i);
       
         if(number.intValue() < min){
            min = number.intValue();
         }
      }
      return min;
   }
   
   private static int getSum(List numbers){
      int sum = (int)(numbers.get(0));
       
      for(int i=1;i < numbers.size();i++){
         sum += (int)numbers.get(i);
      }
      return sum;
   }
   
   private static int getAverage(List numbers){
      return getSum(numbers) / numbers.size();
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Testeras follows −

$java Java8Tester

It should produce the following result −

Using Java 7:
List: [abc, , bc, efg, abcd, , jkl]
Empty Strings: 2
Strings of length 3: 3
Filtered List: [abc, bc, efg, abcd, jkl]
Merged String: abc, bc, efg, abcd, jkl
Squares List: [9, 4, 49, 25]
List: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Highest number in List : 19
Lowest number in List : 1
Sum of all numbers : 85
Average of all numbers : 9
Random Numbers:
-1279735475
903418352
-1133928044
-1571118911
628530462
18407523
-881538250
-718932165
270259229
421676854
Using Java 8:
List: [abc, , bc, efg, abcd, , jkl]
Empty Strings: 2
Strings of length 3: 3
Filtered List: [abc, bc, efg, abcd, jkl]
Merged String: abc, bc, efg, abcd, jkl
Squares List: [9, 4, 49, 25]
List: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Highest number in List : 19
Lowest number in List : 1
Sum of all numbers : 85
Average of all numbers : 9.444444444444445
Random Numbers:
-1009474951
-551240647
-2484714
181614550
933444268
1227850416
1579250773
1627454872
1683033687
1798939493
Empty Strings: 2


Optional Class
Optional is a container object which is used to contain not-null objects. Optional object is used to represent null with absent value. This class has various utility methods to facilitate code to handle values as ‘available’ or ‘not available’ instead of checking null values. It is introduced in Java 8 and is similar to what Optional is in Guava.
Class Declaration

Following is the declaration for java.util.Optional class −

public final class Optional extends Object

Class Method
1)  static Optional empty()
Returns an empty Optional instance.


2) boolean equals(Object obj)
Indicates whether some other object is "equal to" this Optional.


3) Optional filter(Predicate predicate)
If a value is present and the value matches a given predicate, it returns an Optional describing the value, otherwise returns an empty Optional.


4) Optional flatMap(Function> mapper)
If a value is present, it applies the provided Optional-bearing mapping function to it, returns that result, otherwise returns an empty Optional.


5) T get()
If a value is present in this Optional, returns the value, otherwise throws NoSuchElementException.


6) int hashCode()
Returns the hash code value of the present value, if any, or 0 (zero) if no value is present.


7) void ifPresent(Consumer consumer)
If a value is present, it invokes the specified consumer with the value, otherwise does nothing.


8) boolean isPresent()
Returns true if there is a value present, otherwise false.


9 ) Optional map(Function mapper)
If a value is present, applies the provided mapping function to it, and if the result is non-null, returns an Optional describing the result.


10) static Optional of(T value)
Returns an Optional with the specified present non-null value.
 

11) static Optional ofNullable(T value)
Returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional.
 

12) T orElse(T other)
Returns the value if present, otherwise returns other.


13) T orElseGet(Supplier other)
Returns the value if present, otherwise invokes other and returns the result of that invocation.


14) T orElseThrow(Supplier exceptionSupplier)
Returns the contained value, if present, otherwise throws an exception to be created by the provided supplier.
 

15) String toString()
Returns a non-empty string representation of this Optional suitable for debugging.
Note − This class inherits methods from the java.lang.Object class.
 

Optional Example

To understand how Optional is used in practice, let us see the following example. Write the following program, execute and verify result to get more insight of it.
Java8Tester.java

import java.util.Optional;

public class Java8Tester {
   public static void main(String args[]){
  
      Java8Tester java8Tester = new Java8Tester();
      Integer value1 = null;
      Integer value2 = new Integer(10);
       
      //Optional.ofNullable - allows passed parameter to be null.
      Optional a = Optional.ofNullable(value1);
       
      //Optional.of - throws NullPointerException if passed parameter is null
      Optional b = Optional.of(value2);
      System.out.println(java8Tester.sum(a,b));
   }
   
   public Integer sum(Optional a, Optional b){
   
      //Optional.isPresent - checks the value is present or not
       
      System.out.println("First parameter is present: " + a.isPresent());
      System.out.println("Second parameter is present: " + b.isPresent());
       
      //Optional.orElse - returns the value if present otherwise returns
      //the default value passed.
      Integer value1 = a.orElse(new Integer(0));
       
      //Optional.get - gets the value, value should be present
      Integer value2 = b.get();
      return value1 + value2;
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

First parameter is present: false
Second parameter is present: true
10


Nashorn JavaScript
With Java 8, Nashorn, a much improved javascript engine is introduced, to replace the existing Rhino. Nashorn provides 2 to 10 times better performance, as it directly compiles the code in memory and passes the bytecode to JVM. Nashorn uses invokedynamics feature, introduced in Java 7 to improve performance.
jjs

For Nashorn engine, JAVA 8 introduces a new command line tool, jjs, to execute javascript codes at console.
Interpreting js File

Create and save the file sample.js in c:\> JAVA folder.
sample.js

print('Hello World!');

Open console and use the following command.

$jjs sample.js

It will produce the following output:

Hello World!

jjs in Interactive Mode

Open the console and use the following command.

$jjs
jjs> print("Hello, World!")
Hello, World!
jjs> quit()
>>

Pass Arguments

Open the console and use the following command.

$jjs -- a b c
jjs> print('letters: ' +arguments.join(", "))
letters: a, b, c
jjs>

Calling JavaScript from Java

Using ScriptEngineManager, JavaScript code can be called and interpreted in Java.
Example

Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;

public class Java8Tester {
   public static void main(String args[]){
  
      ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
      ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");
       
      String name = "Mahesh";
      Integer result = null;
     
      try {
         nashorn.eval("print('" + name + "')");
         result = (Integer) nashorn.eval("10 + 2");
        
      }catch(ScriptException e){
         System.out.println("Error executing script: "+ e.getMessage());
      }
     
      System.out.println(result.toString());
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following result −

Mahesh
12

Calling Java from JavaScript

The following example explains how to import and use Java classes in java script −
sample.js

var BigDecimal = Java.type('java.math.BigDecimal');

function calculate(amount, percentage) {
   var result = new BigDecimal(amount).multiply(
   new BigDecimal(percentage)).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_EVEN);  
   return result.toPlainString();
}

var result = calculate(568000000000000000023,13.9);
print(result);

Open the console and use the following command.

$jjs sample.js

It should produce the following output −

78952000000000000003.20

New Date/Time API
In Java 8, a new Date-Time API is introduced to cover the following drawbacks of old date-time API

    Not thread safe − java.util.Date is not thread safe, thus developers have to deal with concurrency issue while using date. The new date-time API is immutable and does not have setter methods.

    Poor design − Default Date starts from 1900, month starts from 1, and day starts from 0, so no uniformity. The old API had less direct methods for date operations. The new API provides numerous utility methods for such operations.

    Difficult time zone handling − Developers had to write a lot of code to deal with timezone issues. The new API has been developed keeping domain-specific design in mind.

Java 8 introduces a new date-time API under the package java.time. Following are some of the important classes introduced in java.time package −

    Local − Simplified date-time API with no complexity of timezone handling.
    Zoned − Specialized date-time API to deal with various timezones.
    Local Data-Time API
    LocalDate/LocalTime and LocalDateTime classes simplify the development where timezones are    not required. Let's see them in action.


Java8Tester.java

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.Month;

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester java8tester = new Java8Tester();
      java8tester.testLocalDateTime();
   }
   
   public void testLocalDateTime(){
   
      // Get the current date and time
      LocalDateTime currentTime = LocalDateTime.now();
      System.out.println("Current DateTime: " + currentTime);
       
      LocalDate date1 = currentTime.toLocalDate();
      System.out.println("date1: " + date1);
       
      Month month = currentTime.getMonth();
      int day = currentTime.getDayOfMonth();
      int seconds = currentTime.getSecond();
       
      System.out.println("Month: " + month +"day: " + day +"seconds: " + seconds);
       
      LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
      System.out.println("date2: " + date2);
       
      //12 december 2014
      LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);
      System.out.println("date3: " + date3);
       
      //22 hour 15 minutes
      LocalTime date4 = LocalTime.of(22, 15);
      System.out.println("date4: " + date4);
       
      //parse a string
      LocalTime date5 = LocalTime.parse("20:15:30");
      System.out.println("date5: " + date5);
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

Current DateTime: 2014-12-09T11:00:45.457
date1: 2014-12-09
Month: DECEMBERday: 9seconds: 45
date2: 2012-12-10T11:00:45.457
date3: 2014-12-12
date4: 22:15
date5: 20:15:30

Zoned Data-Time API
Zoned date-time API is to be used when time zone is to be considered. Let us see them in action −

Java8Tester.java

import java.time.ZonedDateTime;
import java.time.ZoneId;

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester java8tester = new Java8Tester();
      java8tester.testZonedDateTime();
   }
   
   public void testZonedDateTime(){
   
      // Get the current date and time
      ZonedDateTime date1 = ZonedDateTime.parse("2007-12-03T10:15:30+05:30[Asia/Karachi]");
      System.out.println("date1: " + date1);
       
      ZoneId id = ZoneId.of("Europe/Paris");
      System.out.println("ZoneId: " + id);
       
      ZoneId currentZone = ZoneId.systemDefault();
      System.out.println("CurrentZone: " + currentZone);
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

date1: 2007-12-03T10:15:30+05:00[Asia/Karachi]
ZoneId: Europe/Paris
CurrentZone: Etc/UTC

Chrono Units Enum
java.time.temporal.ChronoUnit enum is added in Java 8 to replace the integer values used in old API to represent day, month, etc. Let us see them in action −
Java8Tester.java

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester java8tester = new Java8Tester();
      java8tester.testChromoUnits();
   }
   
   public void testChromoUnits(){
   
      //Get the current date
      LocalDate today = LocalDate.now();
      System.out.println("Current date: " + today);
       
      //add 1 week to the current date
      LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
      System.out.println("Next week: " + nextWeek);
       
      //add 1 month to the current date
      LocalDate nextMonth = today.plus(1, ChronoUnit.MONTHS);
      System.out.println("Next month: " + nextMonth);
       
      //add 1 year to the current date
      LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
      System.out.println("Next year: " + nextYear);
       
      //add 10 years to the current date
      LocalDate nextDecade = today.plus(1, ChronoUnit.DECADES);
      System.out.println("Date after ten year: " + nextDecade);
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following result −

Current date: 2014-12-10
Next week: 2014-12-17
Next month: 2015-01-10
Next year: 2015-12-10
Date after ten year: 2024-12-10

Period & Duration
With Java 8, two specialized classes are introduced to deal with the time differences −

    Period − It deals with date based amount of time.
    Duration − It deals with time based amount of time.


Let us understand them with an example −
Java8Tester.java

import java.time.temporal.ChronoUnit;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Duration;
import java.time.Period;

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester java8tester = new Java8Tester();
      java8tester.testPeriod();
      java8tester.testDuration();
   }
   
   public void testPeriod(){
   
      //Get the current date
      LocalDate date1 = LocalDate.now();
      System.out.println("Current date: " + date1);
       
      //add 1 month to the current date
      LocalDate date2 = date1.plus(1, ChronoUnit.MONTHS);
      System.out.println("Next month: " + date2);
     
      Period period = Period.between(date2, date1);
      System.out.println("Period: " + period);
   }
   
   public void testDuration(){
      LocalTime time1 = LocalTime.now();
      Duration twoHours = Duration.ofHours(2);
       
      LocalTime time2 = time1.plus(twoHours);
      Duration duration = Duration.between(time1, time2);
       
      System.out.println("Duration: " + duration);
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

Current date: 2014-12-10
Next month: 2015-01-10
Period: P-1M
Duration: PT2H

Temporal Adjusters
TemporalAdjuster is used to perform the date mathematics. For example, get the "Second Saturday of the Month" or "Next Tuesday". Let us see an example of it −
Java8Tester.java

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.time.DayOfWeek;

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester java8tester = new Java8Tester();
      java8tester.testAdjusters();
   }
   
   public void testAdjusters(){
   
      //Get the current date
      LocalDate date1 = LocalDate.now();
      System.out.println("Current date: " + date1);
       
      //get the next tuesday
      LocalDate nextTuesday = date1.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
      System.out.println("Next Tuesday on : " + nextTuesday);
       
      //get the second saturday of next month
      LocalDate firstInYear = LocalDate.of(date1.getYear(),date1.getMonth(), 1);
      LocalDate secondSaturday = firstInYear.with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY)).with(TemporalAdjusters.next(DayOfWeek.SATURDAY));
      System.out.println("Second Saturday on : " + secondSaturday);
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following result −

Current date: 2014-12-10
Next Tuesday on : 2014-12-16
Second Saturday on : 2014-12-13

Backward Compatibility
A toInstant() method is added to the original Date and Calendar objects, which can be used to convert them to the new Date-Time API. Use an ofInstant(Insant,ZoneId) method to get a LocalDateTime or ZonedDateTime object. Let us understand it with an example −
Java8Tester.java

import java.time.LocalDateTime;
import java.time.ZonedDateTime;

import java.util.Date;

import java.time.Instant;
import java.time.ZoneId;

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester java8tester = new Java8Tester();
      java8tester.testBackwardCompatability();
   }
   
   public void testBackwardCompatability(){
   
      //Get the current date
      Date currentDate = new Date();
      System.out.println("Current date: " + currentDate);
       
      //Get the instant of current date in terms of milliseconds
      Instant now = currentDate.toInstant();
      ZoneId currentZone = ZoneId.systemDefault();
       
      LocalDateTime localDateTime = LocalDateTime.ofInstant(now, currentZone);
      System.out.println("Local date: " + localDateTime);
       
      ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(now, currentZone);
      System.out.println("Zoned date: " + zonedDateTime);
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

Current date: Wed Dec 10 05:44:06 UTC 2014
Local date: 2014-12-10T05:44:06.635
Zoned date: 2014-12-10T05:44:06.635Z[Etc/UTC]


Base64
With Java 8, Base64 has finally got its due. Java 8 now has inbuilt encoder and decoder for Base64 encoding. In Java 8, we can use three types of Base64 encoding −

    Simple − Output is mapped to a set of characters lying in A-Za-z0-9+/. The encoder does not add any line feed in output, and the decoder rejects any character other than A-Za-z0-9+/.

    URL − Output is mapped to set of characters lying in A-Za-z0-9+_. Output is URL and filename safe.

    MIME − Output is mapped to MIME friendly format. Output is represented in lines of no more than 76 characters each, and uses a carriage return '\r' followed by a linefeed '\n' as the line separator. No line separator is present to the end of the encoded output.

Nested Classes
1) static class Base64.Decoder
This class implements a decoder for decoding byte data using the Base64 encoding scheme as specified in RFC 4648 and RFC 2045.

2) static class Base64.Encoder
This class implements an encoder for encoding byte data using the Base64 encoding scheme as specified in RFC 4648 and RFC 2045.

 Method Name & Description

1 ) static Base64.Decoder getDecoder()
Returns a Base64.Decoder that decodes using the Basic type base64 encoding scheme.

2) static Base64.Encoder getEncoder()
Returns a Base64.Encoder that encodes using the Basic type base64 encoding scheme.

3) static Base64.Decoder getMimeDecoder()
Returns a Base64.Decoder that decodes using the MIME type base64 decoding scheme.

4) static Base64.Encoder getMimeEncoder()
Returns a Base64.Encoder that encodes using the MIME type base64 encoding scheme.

5) static Base64.Encoder getMimeEncoder(int lineLength, byte[] lineSeparator)
Returns a Base64.Encoder that encodes using the MIME type base64 encoding scheme with specified line length and line separators.

6) static Base64.Decoder getUrlDecoder()
Returns a Base64.Decoder that decodes using the URL and Filename safe type base64 encoding scheme.

7) static Base64.Encoder getUrlEncoder()
Returns a Base64.Encoder that encodes using the URL and Filename safe type base64 encoding scheme.

Methods Inherited
Base64 class inherits few methods from the java.lang.Object class.

Base64 Example

Let us see an example to see Base64 in practice −
Java8Tester.java

import java.util.Base64;
import java.util.UUID;
import java.io.UnsupportedEncodingException;

public class HelloWorld {
   public static void main(String args[]){
      try {
       
         // Encode using basic encoder
         String base64encodedString = Base64.getEncoder().encodeToString("TutorialsPoint?java8".getBytes("utf-8"));
         System.out.println("Base64 Encoded String (Basic) :" + base64encodedString);
       
         // Decode
         byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);
       
         System.out.println("Original String: " + new String(base64decodedBytes, "utf-8"));
         base64encodedString = Base64.getUrlEncoder().encodeToString("TutorialsPoint?java8".getBytes("utf-8"));
         System.out.println("Base64 Encoded String (URL) :" + base64encodedString);
       
         StringBuilder stringBuilder = new StringBuilder();
       
         for (int i = 0; i < 10; ++i) {
            stringBuilder.append(UUID.randomUUID().toString());
         }
       
         byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
         String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);
         System.out.println("Base64 Encoded String (MIME) :" + mimeEncodedString);
        
      }catch(UnsupportedEncodingException e){
         System.out.println("Error :" + e.getMessage());
      }
   }
}

Verify the Result

Compile the class using javac compiler as follows −

$javac Java8Tester.java

Now run the Java8Tester as follows −

$java Java8Tester

It should produce the following output −

Base64 Encoded String (Basic) :VHV0b3JpYWxzUG9pbnQ/amF2YTg=
Original String: TutorialsPoint?java8
Base64 Encoded String (URL) :VHV0b3JpYWxzUG9pbnQ_amF2YTg=
Base64 Encoded String (MIME) :ZWJjY2YzZWUtYmUwZC00Yjg1LTlkYjUtNWUyMzBlNWI
4ZGQ4ZjE1NGJmMjEtNTdkNi00YzM1LTg4
MzYtNDZlYzNhZDM2NTdkZmQzY2RiNzMtMTU1OC00ZjBmLWFmZGQtM2YyZWU3MDYzZjQwNzVhY
WQ0
ODctZWEyZS00YzM2LWEyZmUtOGVkMmNjMGNmZGM3MTg5YWUyZGQtMzg4MS00M2NkLWI2NDEtZ
jNh
Zjk2OGIxZDU2YzkzODZlYTUtNjljNC00ZmIyLTkzYTQtMzVlOTFlNjdlY2E0MDcwNWExMWItM
mE4
Yy00OTljLTg2NmItMjE3ZTZmMmIyY2NiNzI2MjAwZWQtMjI0NC00YzJhLWJiMGItOTczMDJkM
zIx
NGFkY2QyZmVhODItNmUyOS00MWNjLWFlODItNzdmNzRhYmQ4NGU5ZGQ3ZjY3NzktZjgwYi00M
zlk
LTlmNDgtOTNlNTIwYzIzZDcyHow to Rest ArrayList In Java


Read More 

Java 7 features
How to Reset Arraylist In Java
How HashMap Work in Java
Why wait (), notify () and notifyAll () must be called from synchronized block or method in Java
XPath to locate Information in XML
Internals of Garbage Collector
Reference Type in Java
Different Ways to Create ObjectClass Loaders in Java
Producer Consumer Problem
Why String is Final in Java
Singleton Class using Enum
JSON tutorial
Exceptional Handling in Java