Friday, January 22, 2016

Java 7 Features That I Like


If Generics is my most favorite feature of Java 5, Java 7 has several features that I like because they make my life easier as a developer and my codes cleaner and shorter. Here are my favorite Java 7 features in no particular order:

Using String in switch statements

This feature is part of my wishlist since I saw that C# has this capability of using String type in switch statements. Before Java 7, the variable used in switch statement can only be integer, byte, short, char and enum. Now let’s take a look at the conventional way of comparing strings using if-else statements.


package com.melodycancode.java;

public class StringComparisonDemo1 {

 public static void main(String[] args) {
  String selectedOS = "Linux";
  
  if ("Windows".equals(selectedOS)) {
   System.out.println("You're using Windows operating system.");
  } else if ("Mac OS".equals(selectedOS)) {
   System.out.println("You're using Mac OS operating system.");
  } else if ("Linux".equals(selectedOS)) {
   System.out.println("You're using Linux operating system.");
  } else {
   System.out.println("Your operating system is not supported");
  }
 }
}

In Java 7, the above code can be simplified using String in switch statement.

package com.melodycancode.java;

public class StringComparisonDemo2 {

 public static void main(String[] args) {
  String selectedOS = "Linux";
  
  switch(selectedOS) {
   case "Windows":
    System.out.println("You're using Windows operating system.");
    break;
   case "Mac OS":
    System.out.println("You're using Mac OS operating system.");
    break;
   case "Linux":
    System.out.println("You're using Linux operating system.");
    break;
   default:
    System.out.println("Your operating system is not supported");
    break;
  }
 }
}

Take note though that string comparison in switch statement is case-sensitive.


Using diamond <> operator in generics declaration

Let’s say we need to declare a map of persons using generics with string as key and list of person as value. The declaration will look like this:

Map<String, List<Person>> personMap = new HashMap<String, List<Person>>();

The above declaration is quite verbose and not too readable. In Java 7, this can be rewritten as:

Map<String, List<Person>> personMap = new HashMap<>();

This time we use the diamond operator <> to replace the redundant generics declaration. The compiler will automatically infer the type parameters based on the left-hand-side of the declaration.

Multi-catch exception handling

Normally, if you called a method that throws multiple exceptions in the try block, you have to handle each exception that is thrown.

package com.melodycancode.java;

import java.text.ParseException;

public class MultiCatchDemo1 {
 
 public static void main(String[] args) {
  try {
   methodThrowsMultipleExceptions();
  } catch (NumberFormatException e) {
   e.printStackTrace();
  } catch (ParseException e) {
   e.printStackTrace();
  }
 }

 public static void methodThrowsMultipleExceptions() 
   throws ParseException, NumberFormatException {

 }
}

Most of the time, the exceptions thrown by a method are handled in the same way (e.g. log the error) so it would be better if there is a way to handle multiple exceptions using just a single catch block. Luckily, this feature is now supported in Java 7 as shown below:


package com.melodycancode.java;

import java.text.ParseException;

public class MultiCatchDemo2 {

 public static void main(String[] args) {
  try {
   methodThrowsMultipleExceptions();
  } catch (NumberFormatException | ParseException e) {
   e.printStackTrace();
  } 
 }

 public static void methodThrowsMultipleExceptions() 
   throws ParseException, NumberFormatException {

 }
}

As you can see, we use the | operator to handle multiple exceptions in one catch block.

Try-with-resource statements

Whenever we use resources in Java (e.g. FileInputStream, FileOutputStream, etc.), we need to manually close them in the try-finally block. What I don’t like about this approach is that you also need to enclose the closing of the resources inside another try-catch block which looks like this:
package com.melodycancode.java;

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ResourceDemo1 {

 public static void main(String[] args) {
  FileOutputStream fos = null;
  DataOutputStream dos = null;
  
  try {
   fos = new FileOutputStream("SongList.txt");
   dos = new DataOutputStream(fos);
   
   dos.writeUTF("Hello by Adele");
  } catch (IOException ioe) {
   ioe.printStackTrace();
  } finally {
   try {
    if (fos != null) {
     fos.close();
    }
    
    if (dos != null) {
     dos.close();
    }
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }
}

The above codes are obviously an eyesore. In Java 7, any resource that implements java.lang.AutoCloseable interface can now be closed automatically using the try-with-resource statements. This feature is actually equivalent to C#’s using block. Now we only need to declare the resources in try block as parameters and these resources will automatically close as soon as the control exits the try block as demonstrated below:

package com.melodycancode.java;

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ResourceDemo2 {

 public static void main(String[] args) {
  try (FileOutputStream fos = new FileOutputStream("SongList.txt");
    DataOutputStream dos = new DataOutputStream(fos)) {
   dos.writeUTF("25 Minutes by Michael Learns to Rock");
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

Notice how the codes became shorter compared to the previous one. No more ugly-duckling code :)

How about you? What are your favorite Java 7 features?

No comments:

Post a Comment