Basic useful Java7 language changes

Switch statement
The Java switch statement allows you to write an efficient multiple-branch statement without lots and lots of ugly nested ifs – like this: In Java 6 and before, the values for the cases can only be constants of:

  • type byte, char, short, int (or, technically, their reference-type
  • equivalents Byte, Character, Short, Integer) or enum constants.

With 7, the spec has been extended to allow for Strings to be used as well – they’re constants after all.

package edvorkin;

/**
 *
 * @author edvorkin
 * The Java switch statement allows you to write an efficient multiple-branch 
 * statement without lots and lots of ugly nested ifs - like this:
 */


/* Java 1.6  */

public class StringInSwitch {
    
    public static void main(String[] args){
            StringInSwitch sw=new StringInSwitch();
            sw.printDay(3);
            sw.printDay("Friday");
}

    public void printDay(int dayOfWeek) {
        switch (dayOfWeek) {
            case 0:
                System.out.println("Sunday");
                break;
            case 1:
                System.out.println("Monday");
                break;
            case 2:
                System.out.println("Tuesday");
                break;
            case 3:
                System.out.println("Wednesday");
                break;
            case 4:
                System.out.println("Thursday");
                break;
            case 5:
                System.out.println("Friday");
                break;
            case 6:
                System.out.println("Saturday");
                break;
            default:
                System.err.println("Error!");
                break;
        }
    }
    /*In Java 6 and before, the values for the cases can only be constants of 
     * type byte, char, short, int (or, technically, their reference-type 
     * equivalents Byte, Character, Short, Integer) or enum constants. 
     * With 7, the spec has been extended to allow for Strings 
     * to be used as well - they’re constants after all:*/

    public void printDay(String dayOfWeek) {
        switch (dayOfWeek) {
            case "Sunday":
                System.out.println("Dimanche");
                break;
            case "Monday":
                System.out.println("Lundi");
                break;
            case "Tuesday":
                System.out.println("Mardi");
                break;
            case "Wednesday":
                System.out.println("Mercredi");
                break;
            case "Thursday":
                System.out.println("Jeudi");
                break;
            case "Friday":
                System.out.println("Vendredi");
                break;
            case "Saturday":
                System.out.println("Samedi");
                break;
                
            default:
                System.out.println("Error: '" + dayOfWeek + "' is not a day of the week");
        }
    }
}

Diamond Syntax
One of the problems with generics is that the definitions and setup of instances can be really verbose. Let’s suppose that you have some object, whom you identify by a objectid (which is an integer) and each object has some lookup tables (possibly more than one), and the tables are specific to each object. What would that look like in code?
Map> objectsLists = new HashMap>();
This is a lot of code and code on the right is just a duplicate of what we have on the left. Is it make much sense to have:
Map> objectsLists = new HashMap<>();
    
    Map<Integer, List<String>> objectsLists6 = new HashMap<Integer, List<String>>();
    /* new code java 7*/
    Map<Integer, List<String>> objectsLists7 = new HashMap<>();

This form is called “Diamond Syntax” because, well, the shortened type information looks like a diamond. The proper name in the proposal is “Improved Type Inference for Generic Instance Creation”, which is a real mouthful, and has ITIGIC as an acronym, which just sounds stupid – so Diamond Syntax it is.

Improved Exception Handling
There are two parts to this improvement – multi-catch and final rethrow. To see why they’re a help, consider the following Java 6 code, which tries to find, open and parse a config file, and handles a number of different possible exceptions:

public Configuration getConfig(String fileName_) {
        Configuration cfg = null;
        try {
            String fileText = getFile(fileName_);
            cfg = verifyConfig(parseConfig(fileText));
        } catch (FileNotFoundException fnfx) {
            System.err.println("Config file '" + fileName_ + "' is missing");
        } catch (IOException e) {
            System.err.println("Error while processing file '" + fileName_)
        } catch (ConfigurationException e) {
            System.err.println("Config file '" + fileName_ + "' is not consistent");
        } catch (ParseException e) {
        }
        System.err.println("Config file '" + fileName_ + "' is malformed");
    }
    
    return cfg ;
}

This is a method which can encounter a number of different exceptional conditions:

  • The config file may not exist
  • It may disappear whilst we’re trying to read from it
  • It may be malformed syntactically
  • It may have invalid information in it

It may be nice to group all exceptions together, or group together exceptions related to incorrect file content vs io exceptions. Java 7 allow us to do that:

   public Configuration getConfig(String fileName_) {
        Configuration cfg = null;
        try {
            String fileText = getFile(fileName_);
            cfg = verifyConfig(parseConfig(fileText));
        } catch (FileNotFoundException | ParseException | ConfigurationException e) {
            System.err.println("Config file '" + fileName_ + "' is missing or malformed");
        } catch (IOException iox) {
        }
        System.err.println("Error while processing file '" + fileName_ );
} 

return cfg;
}

An additional bit of new syntax is for helping with rethrowing exceptions. In many cases, developers may want to manipulate a thrown exception before rethrowing it. The problem comes that in previous versions of Java, we often see code this:
try {
            doSomethingWhichMightThrowIOException();
            doSomethingElseWhichMightThrowSQLException();
        } catch (Exception e) {
        }
        
        ...throw e;
    }

This forces the programmer to declare the exception signature of this code as Exception – the real dynamic type of the exception has been swallowed. However, it’s relatively easy to see that the exception can only be an IOException or a SQLException, and if we can see it, then so can the compiler. In this snippet, we’ve made a single word change to use the next Java 7 syntax:
public Configuration getConfig(String fileName_) {
        try {
            doSomethingWhichMightThrowIOException();
            doSomethingElseWhichMightThrowSQLException();
        } catch (final Exception e) {
        }
        
        ...throw e;
    }

The appearance of the “final” keyword indicates that the type that is actually thrown is the runtime type of the exception that was actually encountered – in this example this would either be IOException or SQLException. This is referred to as “final rethrow”, and can protect against throwing an overly general type here, which then has to be caught by a very general catch in a higher scope. The final keyword is actually optional in the above example, but in practice, we’ve found that it helps to write it in while adjusting to the new semantics of catch and rethrow.
Try-with-resources (TWR)
The basic idea is to allow a resource (e.g. a file, or something a bit like one) to be scoped to a block in such a way that the resource is automatically closed when control exits the block.
This is an important change, for the simple reason that virtually no-one gets manual handling of resource closing 100% right.
As an example, let’s consider some Java 7 code for saving code from the web. As the name suggests, url is a URL object that points at the entity we want to download, and file is a File object where we want to save what we’re downloading.
try ( FileOutputStream fos = new FileOutputStream(file); InputStream is = url.openStream()) {
               byte[] buf = new byte[4096];
               int len;
                while ((len = is.read(buf)) > 0) {
                            fos.write (buf, 0, len);
                        }
   }

The resources are used by the block, and then automatically disposed of when you’re done with them.
This is a big help in writing error-free code. To see just how much, consider how you would write a similar block of code to read from a stream coming from a URL and write to a file with Java 6.
 InputStream is = null;
        try {
            is = url.openStream();
            OutputStream out = new FileOutputStream(file);
            try {
                byte[] buf = new byte[4096];
                int n;
                while ((n = is.read(buf)) >= 0) {
                    out.write(buf, 0, n);
                }
            } catch (IOException iox) {
                
                 } finally {
                try {
                    out.close();
                } catch (IOException closeOutx) {
                }
            }
            
       
        } catch (FileNotFoundException fnfx) {
            
          
        } catch (IOException openx) {
            
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException closeInx) {
            }
        }
        
    
    }

Seven lines of code vs 35 lines plus it’s just much less error prone – the compiler is not susceptible to the mistakes which basically every developer will make when trying to write this type of code manually. One other aspect of TWR is the appearance of enhanced stack traces and suppressed exceptions. Prior to 7 exception information could be swallowed when handling resources. This possibility also exists with TWR, so the stack traces have been enhanced to allow the developer to see the type information of exceptions that would otherwise be lost.
For your own code, however, you should definitely use TWR whenever you need to work with resources– it will help you avoid bugs in your exception handling. Some resources, most notably JDBC 4.1, were rewritten to support autoclosable functionality. To learn more about resource management check out Better Resource Management with Java SE 7: Beyond Syntactic Sugar
Tose are some of the small changes introduced in Java 7. There are much bigger and important changes in this release – new IO API, new help with concurrency programming, JVM enhancements in performance and others languages support. I am going to look into new IO API and concurrency changes.
Examples in this post are from a new book by Benjamin J Evans and Martijn Verburg “The Well-Grounded Java Developer: Java 7 and Polyglot Programming on the JVM”. You can follow their blog – Java7developer.com to learn more about Java 7.

Submit a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>