Monday, 3 October 2011

7 new cool features in Java 7


1. Strings in switch Statements (doc)
Did you know previous to Java 7 you could only do a switch on charbyteshortint,CharacterByteShortInteger, or an enum type (spec)? Java 7 adds Strings making the switch instruction much friendlier to String inputs. The alternative before was to do with with if/else if/else statements paired with a bunch of String.equals() calls. The result is much cleaner and compact code.
  1. public void testStringSwitch(String direction) {  
  2.     switch (direction) {  
  3.          case "up":  
  4.              y--;  
  5.          break;  
  6.   
  7.          case "down":  
  8.              y++;  
  9.          break;  
  10.   
  11.          case "left":  
  12.              x--;  
  13.          break;  
  14.   
  15.          case "right":  
  16.              x++;  
  17.          break;  
  18.   
  19.         default:  
  20.             System.out.println("Invalid direction!");  
  21.         break;  
  22.     }  
  23. }  
2. Type Inference for Generic Instance Creation (doc)
Previously when using generics you had to specify the type twice, in the declaration and the constructor;
  1. List<String> strings = new ArrayList<String>();  
In Java 7, you just use the diamond operator without the type;
  1. List<String> strings = new ArrayList<>();  
If the compiler can infer the type arguments from the context, it does all the work for you. Note that you have always been able do a “new ArrayList()” without the type, but this results in an unchecked conversion warning.
Type inference becomes even more useful for more complex cases;
  1. // Pre-Java 7  
  2. // Map<String,Map<String,int>>m=new HashMap<String, Map<String,int>>();  
  3.   
  4. // Java 7  
  5. Map<String, Map<String, int>> m = new HashMap<>();  
3. Multiple Exception Handling Syntax (doc)
Tired of repetitive error handling code in “exception happy” APIs like java.io andjava.lang.reflect?
  1. try {  
  2.     Class a = Class.forName("wrongClassName");  
  3.     Object instance = a.newInstance();  
  4. catch (ClassNotFoundException ex) {  
  5.     System.out.println("Failed to create instance");  
  6. catch (IllegalAccessException ex) {  
  7.     System.out.println("Failed to create instance");  
  8. catch (InstantiationException ex) {  
  9.    System.out.println("Failed to create instance");  
  10. }  
When the exception handling is basically the same, the improved catch operator now supports multiple exceptions in a single statement separated by “|”.
  1. try {  
  2.     Class a = Class.forName("wrongClassName");  
  3.     Object instance = a.newInstance();  
  4. catch (ClassNotFoundException | IllegalAccessException |  
  5.    InstantiationException ex) {  
  6.    System.out.println("Failed to create instance");  
  7. }  
Sometimes developers use a “catch (Exception ex) to achieve a similar result, but that’s a dangerous idea because it makes code catch exceptions it can’t handle and instead should bubble up (IllegalArgumentException, OutOfMemoryError, etc.).

4. The try-with-resources Statement (doc)
The new try statement allows opening up a “resource” in a try block and automatically closing the resource when the block is done.
For example, in this piece of code we open a file and print line by line to stdout, but pay close attention to the finally block;
  1. try {  
  2.     in = new BufferedReader(new FileReader("test.txt"));  
  3.   
  4.     String line = null;  
  5.     while ((line = in.readLine()) != null) {  
  6.         System.out.println(line);  
  7.     }  
  8. catch (IOException ex) {  
  9.     ex.printStackTrace();  
  10. finally {  
  11.     try {  
  12.         if (in != null) in.close();  
  13.     } catch (IOException ex) {  
  14.         ex.printStackTrace();  
  15.     }  
  16. }  
When using a resource that has to be closed, a finally block is needed to make sure the clean up code is executed even if there are exceptions thrown back (in this example we catch IOException but if we didn’t, finally would still be executed). The new try-with-resources statement allows us to automatically close these resources in a more compact set of code;
  1. try (BufferedReader in=new BufferedReader(new FileReader("test.txt")))  
  2. {  
  3.      String line = null;  
  4.      while ((line = in.readLine()) != null) {  
  5.          System.out.println(line);  
  6.      }  
  7.  } catch (IOException ex) {  
  8.      ex.printStackTrace();  
  9.  }  
So “in” will be closed automatically at the end of the try block because it implements an interface called java.lang.AutoCloseable. An additional benefit is we don’t have to call the awkward IOException on close(), and what this statement does is “suppress” the exception for us (although there is a mechanism to get that exception if needed,Throwable.getSuppressed()).
5. Improved File IO API (docs 12)
There are quite a bit of changes in the java.nio package. Many are geared towards performance improvements, but long awaited enhancements over java.io (specially java.io.File) have finally materialized in a new package called java.nio.file.
For example, to read a small file and print all the lines (see example above);
  1. List<String> lines =  Files.readAllLines(  
  2. FileSystems.getDefault().getPath("test.txt"), StandardCharsets.UTF_8);  
  3.   
  4. for (String line : lines) System.out.println(line);  
java.nio.file.Path is an interface that pretty much serves as a replacement for java.io.File, we need a java.nio.file.FileSystem to get paths, which you can get by using thejava.nio.file.FileSystems factory (getDefault() gives you the default file system).
java.nio.file.Files then provides static methods for file related operations. In this example we can read a whole file much more easily by using readAllLines(). This class also has methods to create symbolic links, which was impossible to do pre-Java 7. Another feature long overdue is the ability to set file permissions for POSIX compliant file systems via the Files.setPosixFilePermissions method. These are all long over due file related operations, impossible without JNI methods or System.exec() hacks.
I didn’t have time to play with it but this package also contains a very interesting capability via the WatchService API which allows notification of file changes. You can for example, register directories you want to watch and get notified when a file is added, removed or updated. Before, this required manually polling the directories, which is not fun code to write.
For more on monitoring changes read this tutorial from Oracle.
6. Support for Non-Java Languages: invokedynamic (doc)
The first new instruction since Java 1.0 was released and introduced in this version is called invokedynamic. Most developers will never interact or be aware of this new bytecode. The exciting part of this feature is that it improves support for compiling programs that use dynamic typing. Java is statically typed (which means you know the type of a variable at compile time) and dynamically typed languages (like Ruby, bash scripts, etc.) need this instruction to support these type of variables.
The JVM already supports many types of non-Java languages, but this instruction makes the JVM more language independent, which is good news for people who would like to implement components in different languages and/or want to inter-operate between those languages and standard Java programs.
7. JLayerPane (doc)
Finally, since I’m a UI guy, I want to mention JLayerPane. This component is similar to the one provided in the JXLayer project. I’ve used JXLayer many times in the past in order to add effects on top of Swing components. Similarly, JLayerPane allows you to decorate a Swing component by drawing on top of it and respond to events without modifying the original component.
This example from the JLayerPane tutorial shows a component using this functionality, providing a “spotlight” effect on a panel.
You could also blur the entire window, draw animations on top of components, or create transition effects.
And that’s just a subset of the features, Java 7 is a long overdue update to the platform and language which offers a nice set of new functionality. The hope is the time from Java 7 to 8 is a lot shorter than from 6 to 7!

No comments:

Post a Comment