Quick catch up of changes in Java 7

Java
Java 7 introduced two major changes:
  • Project Coin
  • NIO-2
Major changes introduced by Project Coin are as follows:
  • try-with-resources construct to automatically close resources (such as IO resources etc.)
  • Enhanced switch statement to handle String
  • Enhanced numeric literals (for improved readability)
  • Handling multiple exceptions in single catch block
  • Diamond syntax for generics to avoid excessive code.
  • Fixes for varargs warnings
NIO-2 changes include:
  • Path construct for dealing with files and files like entities.
  • Files utility class (similar to what Arrays does for arrays)
  • Future and call-back based asynchronous IO
Lets see above features with help of some java code.

switch for Strings


public class TestSwitch {

  public static void testSwitch(String day_of_week) {
	switch(day_of_week.toLowerCase()) {
		case "monday": System.out.println("Monday"); break;
		case "tuesday": System.out.println("Tuesday"); break;
		case "wednesday": System.out.println("Wednesday"); break;
		case "thursday": System.out.println("Thursday"); break;
		case "friday": System.out.println("Friday"); break;
		case "saturday": System.out.println("Saturday"); break;
		case "sunday": System.out.println("Sunday"); break;
		default: System.out.println("Unknown day:" + day_of_week);

	}
  }

  public static void main(String a[]) {
	testSwitch("monday");
	testSwitch("Thursday");
	testSwitch("somwar");
  }

}

Enhanced Numeric Literals

In java7, binary literals can be specified by using 0b prefix. In previous versions, we would have to use parseInt with base 2 to get such behavior (which means calling a method, no ability to use in switch statement, possiblity of RuntimeException due to misrepresentation of binary literal etc.) Consider:

int x1 = Integer.parseInt("1000101100001111", 2);
can now be replaced with:

int x1 = 0b1000101100001111;
In addition, as you may notice above may be difficult to read, Java7 introduces _ to improve readibility:

int x1 = 0b1000_1011_0000_1111;

Enhanced Exception handling

Java7 introduces enhanced exception handling. It now allows you to specify alternate exceptions in single catch block aka multi-catch and final rethrow. The syntax is:

try {

} catch(Exception1 | Exception2 e) {

}
The 'e' will represent super class of Exception1 and Exception2, which is generally Exception or Throwable. The alternate exception i.e. Exception2 must not be superclass of Exception1. For example, following will produce compile time error:

 public static void testNewException(){
          FileReader fr = null;
          try {
                char[] buf = new char[100];
                fr = new FileReader("somefile.txt");
                fr.read(buf);
          } catch(FileNotFoundException | IOException e) {
              e.printStackTrace();
          }
  }
will result:

 error: Alternatives in a multi-catch statement cannot be related by subclassing
          } catch(final FileNotFoundException | IOException e) {
                                                ^
  Alternative FileNotFoundException is a subclass of alternative IOException
1 error
Following is a more better approach:

public static void testNewException(){
          FileReader fr = null;
          try {
                fr = new FileReader("somefile.prop");
                java.util.Properties prop = new java.util.Properties();
                prop.load(fr);
          } catch(FileNotFoundException fne) {
              System.err.println("File Not found");
          } catch(IOException | IllegalArgumentException e) {
              System.err.println("Error handling properties file:" + e.getMessage());
          }
}
The final rethrow allows you to write a single catch block, yet only throw related exception. For instance, in earlier version, we may write this code to signal that calling code should handle the exception:

 public static void testOldGeneralException() throws Exception{
          FileReader fr = null;
          try {
                fr = new FileReader("somefile.prop");
                java.util.Properties prop = new java.util.Properties();
                prop.load(fr);
          } catch(Exception e) {
              System.err.println("Problem dealing with file, rethrowing...");
              throw e;
          }
  }
This allows to consume all exceptions and then throw general exception. However, the calling side also has to handle the general exception .... a bad idea. In Java7, the above can be rewritten as:

 public static void testNewFinalException() throws
      FileNotFoundException, IOException, IllegalArgumentException{
          FileReader fr = null;
          try {
                fr = new FileReader("somefile.prop");
                java.util.Properties prop = new java.util.Properties();
                prop.load(fr);
          } catch(final Exception e) {
              System.err.println("Problem dealing with file, rethrowing...");
              throw e;
          }
  }

public static void main(String a[]) {
        try {
                testNewFinalException();
        }catch(FileNotFoundException fne) {
              System.err.println("File Not found");
        }catch(IOException e) {
              System.err.println("Error handling properties file:" + e.getMessage());
        }

}
You don't have to specify "final" in catch block, but it helps in understanding the semantics.

Try-With-Resource (TWR)

Consider the above example of Filehandling, it misses the close operation. Usually in pre-Java7, we would have to write it as:

public static void testNewException(){
          FileReader fr = null;
          try {
                fr = new FileReader("somefile.prop");
                java.util.Properties prop = new java.util.Properties();
                prop.load(fr);
          } catch(FileNotFoundException fne) {
              System.err.println("File Not found");
          } catch(IOException | IllegalArgumentException e) {
              System.err.println("Error handling properties file:" + e.getMessage());
          } finally {
              if(fr != null) {
               try {
                 fr.close();
               }catch(IOException e) {
                 System.err.println("Error closing file, nothing to do");
               }
              }
          }
  }
I have to write similar code for handling JDBC artifacts as well (ResultSet, Statement, Connection etc.) In Java7, the try syntax has been changed, consider this:

public static void testNewTry() throws FileNotFoundException, IOException{
          try(FileReader fr = new FileReader("somefile.prop")) {
                java.util.Properties prop = new java.util.Properties();
                prop.load(fr);
           }
  }
However, note that try-with-resources block might still cause unclosed resources if you are not careful, consider:

public static void testNewTry2() throws
            FileNotFoundException, IOException{
          try(ObjectInputStream os = new ObjectInputStream(
                                                        new FileInputStream("somefile.bin"))) {
           }
  }
In above example, FileInputStream may open an invalid file, which will cause ObjectInputStream to not be created, however, FileInputStream will not be closed. The correct approach would be:

public static void testNewTryr3() throws
                              FileNotFoundException, IOException{
          try(FileInputStream fis = new FileInputStream("somefile.bin");
ObjectInputStream os = new ObjectInputStream(fis)) {
             //...
           }
}
The above code will make sure to close both FileInputStream and ObjectInputStream.

Diamond syntax for generics

This one is easy and beautiful. Consider following code:
 Map<Integer, Map<String, String>> map = new HashMap<Integer, Map<String,String>>();
The above is declaring a map, identifiable by an integer id which contains another map containing further lookup values. This could be rewritten as:
 Map<Integer, Map<String, String>> map = new HashMap<>();
Java7 will work out the details on right-hand side. It is backward compatible i.e. you can replace the above syntax for your old code. Stay tuned for NIO2 related changes.