Tuesday, August 16, 2011

JDK 7: Strings in switch Statement

Another useful functionality added in JDK7 is the ability to use Strings in switch statements. The Strings are compared using their equals method (hashcode) and as such are case-sensitive.

public String getSeasonFromMonth(String month) {
    String season;

    switch (month) {
        case "December":
        case "January":
        case "February":
            season = "Winter";
            break;

        case "March":
        case "April":
        case "May":
            season = "Spring";
            break;

        case "June":
        case "July":
        case "August":
            season = "Summer";
            break;

        case "September":
        case "October":
        case "November":
            season = "Fall";
            break;

        default:
            throw new IllegalArgumentException("Invalid Month - " + month);
    }

    return season;
}


The compiler also generates more efficient byte-code from the switch statement instead of chained if-then-else statements.

Wednesday, August 10, 2011

JDK 7: Multi-catch and final rethrows

Another neat feature in JDK 7 is the multi-catch feature for exception handling.

If you have code that reads like:

try {
    doSomething();
} catch (ParseException pe) {
    logger.error("Parsing Failed", pe);
    throw pe;
} catch (IOException ioe) {
    logger.error("IO Failed!", ioe);
    throw ioe;
}

It can now be written more concisely as follows:

try {
    doSomething();
} catch (ParseException | IOException e) {
    logger.error("Some exception", e);
    throw e;
}

This really cuts down the boiler plate code for handling the individual exceptions, especially if all you are doing is to simply log and re-throw it. The problem however manifests more generally when we see code that doesn't bother to catch the individual exception but handles it using a generic Exception type.

try {
    doSomething();
} catch (Exception e) {
    logger.error("Some exception", e);
    throw e;
}

In this case the calling method must handle the more generic Exception type and we lose the specific exception. In JDK 7, we could add a keyword, final, to the catch block and specify that the specific type of exception be thrown instead.

try {
    doSomething();
} catch (final Exception e) {
    logger.error("Some exception", e);
    throw e;
}

The "final" is optional, however it adds clarity that the specific exception will be thrown instead of the generic Exception. Here is a more rounded example that explains this:

public class TryCatch {
    public static void main(String ... args) throws Exception {
        doSomething();
    }

    private static void doSomething() throws IOException, ParseException {
        try {
            if (Math.round(Math.random()) %2 == 0) {
                doStuff();
            } else {
                doSomeOtherStuff();
            }
        } catch (final Exception e) {
            out.println("Omg, there was an exception!");
            throw e;
        }
    }

    private static void doStuff() throws IOException {
        throw new IOException("Oops, IO failed!");
    }

    private static void doSomeOtherStuff() throws ParseException {
        throw new ParseException("Uh no, Parsing failed!", 0);
    }
}

Another neat-feature that I think should have been added a long time ago.

JDK 7: Diamond Operator <>

JDK 7 is finally here and comes with it (among other niceties) the much needed syntactic sugar for type inference in generics declaration - the diamond operator (<>).

A declaration such as
Map<String, List<String>> map = new HashMap<String, List<String>>(); 

can now simply be written as
Map<String, List<String>> map = new HashMap<>();

The new operator <> automatically infers the type of the object we are creating based on the type declaration. If you leave out the <> it is still valid syntax of course, however, you will get a warning from the compiler for unchecked conversion like before.

Refer to the Java Tutorial page for more info on Generics Type Inference: http://download.oracle.com/javase/tutorial/java/generics/gentypeinference.html

Time to clean up some code!