Sunday, 31 August 2014

JDK 7 Features

switch on String

Before JDK 7, only integral types can be used as selector for switch-case statement. In JDK 7, you can use a String object as the selector. For example,

String day = "SAT";
switch (day) {
   case "MON": System.out.println("Monday"); break;
   case "TUE": System.out.println("Tuesday"); break;
   case "WED": System.out.println("Wednesday"); break;
   case "THU": System.out.println("Thursday"); break;
   case "FRI": System.out.println("Friday"); break;
   case "SAT": System.out.println("Saturday"); break;
   case "SUN": System.out.println("Sunday"); break;
   default: System.out.println("Invalid");
}

String.equals() method is used in comparison, which is case-sensitive.

Binary Literals with prefix "0b"

In JDK 7, you can express literal values in binary with prefix '0b' (or '0B') for integral types (byte, short, int and long), similar to C/C++ language. Before JDK 7, you can only use octal values (with prefix '0') or hexadecimal values (with prefix '0x' or '0X').

BEFORE:

public void testBinaryIntegralLiterals(){
 
        int binary = 8;
 
        if (binary == 8){
            System.out.println(true);
        } else{
            System.out.println(false);
        }
}

AFTER:

public void testBinaryIntegralLiterals(){
 
        int binary = 0b1000; //2^3 = 8
 
        if (binary == 8){
            System.out.println(true);
        } else{
            System.out.println(false);
        }
}

Underscore for Numeric Literals

In JDK 7, you could insert underscore(s) '_' in between the digits in an numeric literals (integral and floating-point literals) to improve readability. For example,

int anInt = 0b10101000_01010001_01101000_01010001;
double aDouble = 3.1415_9265;
float  aFloat = 3.14_15_92_65f;

Catching Multiple Exception Types

In JDK 7, a single catch block can handle more than one exception types. For example, before JDK 7, you need two catch blocks to catch two exception types although both perform identical task:
try {
   ......
} catch(ClassNotFoundException ex) {
   ex.printStackTrace();
} catch(SQLException ex) {
   ex.printStackTrace();
}
In JDK 7, you could use one single catch block, with exception types separated by '|'.
try {
   ......
} catch(ClassNotFoundException|SQLException ex) {
   ex.printStackTrace();
}

The try-with-resources Statement a.k.a Automatic Resource Management

For example, before JDK 7, we need to use a finally block, to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The code is messy!
import java.io.*;
// Copy from one file to another file character by character.
// Pre-JDK 7 requires you to close the resources using a finally block.
public class FileCopyPreJDK7 {
   public static void main(String[] args) {
      BufferedReader in = null;
      BufferedWriter out = null;
      try {
         in  = new BufferedReader(new FileReader("in.txt"));
         out = new BufferedWriter(new FileWriter("out.txt"));
         int charRead;
         while ((charRead = in.read()) != -1) {
            System.out.printf("%c ", (char)charRead);
            out.write(charRead);
         }
      } catch (IOException ex) {
         ex.printStackTrace();
      } finally {            // always close the streams
         try {
            if (in != null) in.close();
            if (out != null) out.close();
         } catch (IOException ex) {
            ex.printStackTrace();
         }
      }
 
      try {
         in.read();   // Trigger IOException: Stream closed
      } catch (IOException ex) {
         ex.printStackTrace();
      }
   }
}
JDK 7 introduces a try-with-resources statement, which ensures that each of the resources in try(resources) is closed at the end of the statement. This results in cleaner codes.
import java.io.*;
// Copy from one file to another file character by character.
// JDK 7 has a try-with-resources statement, which ensures that
// each resource opened in try() is closed at the end of the statement.
public class FileCopyJDK7 {
   public static void main(String[] args) {
      try (BufferedReader in  = new BufferedReader(new FileReader("in.txt"));
           BufferedWriter out = new BufferedWriter(new FileWriter("out.txt"))) {
         int charRead;
         while ((charRead = in.read()) != -1) {
            System.out.printf("%c ", (char)charRead);
            out.write(charRead);
         }
      } catch (IOException ex) {
         ex.printStackTrace();
      }
   }
}

Type Inference for Generic Instance Creation

import java.util.*;
public class JDK7GenericTest {
   public static void main(String[] args) {
      // Pre-JDK 7
      List<String> lst1 = new ArrayList<String>();
      // JDK 7 supports limited type inference for generic instance creation
      List<String> lst2 = new ArrayList<>();
 
      lst1.add("Mon");
      lst1.add("Tue");
      lst2.add("Wed");
      lst2.add("Thu");
 
      for (String item: lst1) {
         System.out.println(item);
      }
 
      for (String item: lst2) {
         System.out.println(item);
      }
   }
}

Fork Join framework in Java 7


Fork join framework exists even before Java 7 but as a separate JSR. It has been added as new feature in Java 7 to make it part of standard Java 7 core library. Fork join framework allows you to write code which can take advantage of multiple cores present in modern servers. 

Fork-join functionality is achieved by ForkjoinTask object, it has two method fork() and join () Method.
  • The fork() method allows  a new ForkJoinTask to be launched from an existing one.
  • The join() method allows a ForkJoinTask to wait for the completion of another one.
Again ForkjoinTask object has been of two types: RecursiveAction and RecursiveTask which is more specialized form of this instance. While RecursiveAction represent executions that do not yield a return value, Instances of RecursiveTask yield return values.

No comments:

Post a Comment